Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AngleRouterLinea
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 100 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
import "../../BaseRouter.sol";
/// @title AngleRouterLinea
/// @author Angle Core Team
/// @notice Router contract built specifially for Angle use cases on Linea
contract AngleRouterLinea is BaseRouter {
/// @inheritdoc BaseRouter
function _getNativeWrapper() internal pure override returns (IWETH9) {
return IWETH9(0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f);
}
}// SPDX-License-Identifier: GPL-3.0
/*
* █
***** ▓▓▓
* ▓▓▓▓▓▓▓
* ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓
***** //////// ▓▓▓▓▓▓▓
* ///////////// ▓▓▓
▓▓ ////////////////// █ ▓▓
▓▓ ▓▓ /////////////////////// ▓▓ ▓▓
▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓
▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓
▓▓ ,////////////////////////////////////// ▓▓ ▓▓
▓▓ ////////////////////////////////////////// ▓▓
▓▓ //////////////////////▓▓▓▓/////////////////////
,////////////////////////////////////////////////////
.//////////////////////////////////////////////////////////
.//////////////////////////██.,//////////////////////////█
.//////////////////////████..,./////////////////////██
...////////////////███████.....,.////////////////███
,.,////////////████████ ........,///////////████
.,.,//////█████████ ,.......///////████
,..//████████ ........./████
..,██████ .....,███
.██ ,.,█
▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓
▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓
▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓
*/
pragma solidity ^0.8.17;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "./interfaces/external/uniswap/IUniswapRouter.sol";
import "./interfaces/external/IWETH9.sol";
import "./interfaces/ICoreBorrow.sol";
import "./interfaces/IDepositWithReferral.sol";
import "./interfaces/ILiquidityGauge.sol";
import "./interfaces/ISwapper.sol";
import "./interfaces/IVaultManager.sol";
// ============================== STRUCTS AND ENUM =============================
/// @notice Action types
enum ActionType {
transfer,
wrapNative,
unwrapNative,
sweep,
sweepNative,
// Deprecated
uniswapV3,
oneInch,
claimRewards,
// Deprecated
gaugeDeposit,
borrower,
swapper,
mint4626,
deposit4626,
redeem4626,
withdraw4626,
// Deprecated
prepareRedeemSavingsRate,
// Deprecated
claimRedeemSavingsRate,
// Deprecated
swapIn,
// Deprecated
swapOut,
claimWeeklyInterest,
// Deprecated
withdraw,
// Deprecated
mint,
// Deprecated
deposit,
// Deprecated
openPerpetual,
// Deprecated
addToPerpetual,
veANGLEDeposit,
// Deprecated
claimRewardsWithPerps,
deposit4626Referral
}
/// @notice Data needed to get permits
struct PermitType {
address token;
address owner;
uint256 value;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
/// @notice Data to grant permit to the router for a vault
struct PermitVaultManagerType {
address vaultManager;
address owner;
bool approved;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
/// @title BaseRouter
/// @author Angle Core Team
/// @notice Base contract that Angle router contracts on different chains should override
/// @dev Router contracts are designed to facilitate the composition of actions on the different modules of the protocol
abstract contract BaseRouter is Initializable, IDepositWithReferral {
using SafeERC20 for IERC20;
// ================================= REFERENCES ================================
/// @notice Core address handling access control
ICoreBorrow public core;
/// @notice Address of the router used for swaps
IUniswapV3Router public uniswapV3Router;
/// @notice Address of 1Inch router used for swaps
address public oneInch;
uint256[47] private __gap;
// ============================== EVENTS / ERRORS ==============================
error IncompatibleLengths();
error InvalidReturnMessage();
error NotApprovedOrOwner();
error NotGovernor();
error NotGovernorOrGuardian();
error TooSmallAmountOut();
error TransferFailed();
error ZeroAddress();
event ReferredDeposit(
address caller,
address indexed owner,
uint256 assets,
uint256 shares,
address indexed savings,
address indexed referrer
);
/// @notice Deploys the router contract on a chain
function initializeRouter(
address _core,
address _uniswapRouter,
address _oneInch
) public initializer {
if (_core == address(0)) revert ZeroAddress();
core = ICoreBorrow(_core);
uniswapV3Router = IUniswapV3Router(_uniswapRouter);
oneInch = _oneInch;
}
constructor() initializer {}
// =========================== ROUTER FUNCTIONALITIES ==========================
/// @notice Allows composable calls to different functions within the protocol
/// @param paramsPermit Array of params `PermitType` used to do a 1 tx to approve the router on each token (can be done once by
/// setting high approved amounts) which supports the `permit` standard. Users willing to interact with the contract
/// with tokens that do not support permit should approve the contract for these tokens prior to interacting with it
/// @param actions List of actions to be performed by the router (in order of execution)
/// @param data Array of encoded data for each of the actions performed in this mixer. This is where the bytes-encoded parameters
/// for a given action are stored
/// @dev With this function, users can specify paths to swap tokens to the desired token of their choice. Yet the protocol
/// does not verify the payload given and cannot check that the swap performed by users actually gives the desired
/// out token: in this case funds may be made accessible to anyone on this contract if the concerned users
/// do not perform a sweep action on these tokens
function mixer(
PermitType[] memory paramsPermit,
ActionType[] calldata actions,
bytes[] calldata data
) public payable virtual {
// If all tokens have already been approved, there's no need for this step
uint256 permitsLength = paramsPermit.length;
for (uint256 i; i < permitsLength; ++i) {
IERC20Permit(paramsPermit[i].token).permit(
paramsPermit[i].owner,
address(this),
paramsPermit[i].value,
paramsPermit[i].deadline,
paramsPermit[i].v,
paramsPermit[i].r,
paramsPermit[i].s
);
}
// Performing actions one after the others
uint256 actionsLength = actions.length;
for (uint256 i; i < actionsLength; ++i) {
if (actions[i] == ActionType.transfer) {
(address inToken, address receiver, uint256 amount) = abi.decode(data[i], (address, address, uint256));
if (amount == type(uint256).max) amount = IERC20(inToken).balanceOf(msg.sender);
IERC20(inToken).safeTransferFrom(msg.sender, receiver, amount);
} else if (actions[i] == ActionType.wrapNative) {
_wrapNative();
} else if (actions[i] == ActionType.unwrapNative) {
(uint256 minAmountOut, address to) = abi.decode(data[i], (uint256, address));
_unwrapNative(minAmountOut, to);
} else if (actions[i] == ActionType.sweep) {
(address tokenOut, uint256 minAmountOut, address to) = abi.decode(data[i], (address, uint256, address));
_sweep(tokenOut, minAmountOut, to);
} else if (actions[i] == ActionType.sweepNative) {
uint256 routerBalance = address(this).balance;
if (routerBalance != 0) _safeTransferNative(msg.sender, routerBalance);
} else if (actions[i] == ActionType.oneInch) {
(address inToken, uint256 minAmountOut, bytes memory payload) = abi.decode(
data[i],
(address, uint256, bytes)
);
_swapOn1Inch(IERC20(inToken), minAmountOut, payload);
} else if (actions[i] == ActionType.claimRewards) {
(address user, address[] memory claimLiquidityGauges) = abi.decode(data[i], (address, address[]));
_claimRewards(user, claimLiquidityGauges);
} else if (actions[i] == ActionType.borrower) {
(
address collateral,
address vaultManager,
address to,
address who,
ActionBorrowType[] memory actionsBorrow,
bytes[] memory dataBorrow,
bytes memory repayData
) = abi.decode(data[i], (address, address, address, address, ActionBorrowType[], bytes[], bytes));
dataBorrow = _parseVaultIDs(actionsBorrow, dataBorrow, vaultManager, collateral);
_changeAllowance(IERC20(collateral), address(vaultManager), type(uint256).max);
_angleBorrower(vaultManager, actionsBorrow, dataBorrow, to, who, repayData);
} else if (actions[i] == ActionType.swapper) {
(
ISwapper swapperContract,
IERC20 inToken,
IERC20 outToken,
address outTokenRecipient,
uint256 outTokenOwed,
uint256 inTokenObtained,
bytes memory payload
) = abi.decode(data[i], (ISwapper, IERC20, IERC20, address, uint256, uint256, bytes));
_swapper(swapperContract, inToken, outToken, outTokenRecipient, outTokenOwed, inTokenObtained, payload);
} else if (actions[i] == ActionType.mint4626) {
(IERC20 token, IERC4626 savingsRate, uint256 shares, address to, uint256 maxAmountIn) = abi.decode(
data[i],
(IERC20, IERC4626, uint256, address, uint256)
);
_changeAllowance(token, address(savingsRate), type(uint256).max);
_mint4626(savingsRate, shares, to, maxAmountIn);
} else if (actions[i] == ActionType.deposit4626) {
(IERC20 token, IERC4626 savingsRate, uint256 amount, address to, uint256 minSharesOut) = abi.decode(
data[i],
(IERC20, IERC4626, uint256, address, uint256)
);
if (amount == type(uint256).max) amount = token.balanceOf(address(this));
_changeAllowance(token, address(savingsRate), type(uint256).max);
_deposit4626(savingsRate, amount, to, minSharesOut);
} else if (actions[i] == ActionType.deposit4626Referral) {
(
IERC20 token,
IERC4626 savingsRate,
uint256 amount,
address to,
uint256 minSharesOut,
address referrer
) = abi.decode(data[i], (IERC20, IERC4626, uint256, address, uint256, address));
if (amount == type(uint256).max) amount = token.balanceOf(address(this));
_changeAllowance(token, address(savingsRate), type(uint256).max);
_deposit4626Referral(savingsRate, amount, to, minSharesOut, referrer);
} else if (actions[i] == ActionType.redeem4626) {
(IERC4626 savingsRate, uint256 shares, address to, uint256 minAmountOut) = abi.decode(
data[i],
(IERC4626, uint256, address, uint256)
);
if (shares == type(uint256).max) shares = savingsRate.balanceOf(msg.sender);
_redeem4626(savingsRate, shares, to, minAmountOut);
} else if (actions[i] == ActionType.withdraw4626) {
(IERC4626 savingsRate, uint256 amount, address to, uint256 maxSharesOut) = abi.decode(
data[i],
(IERC4626, uint256, address, uint256)
);
_withdraw4626(savingsRate, amount, to, maxSharesOut);
} else {
_chainSpecificAction(actions[i], data[i]);
}
}
}
/// @notice Wrapper built on top of the base `_deposit4626Referral` function to add a proxy enabling to track
/// addresses depositing from a certain referring address into an ERC4626 contract
function deposit4626Referral(
address token,
address savings,
uint256 amount,
address to,
uint256 minSharesOut,
address referrer
) external returns (uint256 sharesOut) {
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
_changeAllowance(IERC20(token), savings, type(uint256).max);
sharesOut = _deposit4626Referral(IERC4626(savings), amount, to, minSharesOut, referrer);
}
/// @notice Wrapper built on top of the base `mixer` function to grant approval to a `VaultManager` contract before performing
/// actions and then revoking this approval after these actions
/// @param paramsPermitVaultManager Parameters to sign permit to give allowance to the router for a `VaultManager` contract
/// @dev In `paramsPermitVaultManager`, the signatures for granting approvals must be given first before the signatures
/// to revoke approvals
/// @dev The router contract has been built to be safe to keep approvals as you cannot take an action on a vault you are not
/// approved for, but people wary about their approvals may want to grant it before immediately revoking it, although this
/// is just an option
function mixerVaultManagerPermit(
PermitVaultManagerType[] memory paramsPermitVaultManager,
PermitType[] memory paramsPermit,
ActionType[] calldata actions,
bytes[] calldata data
) external payable virtual {
uint256 permitVaultManagerLength = paramsPermitVaultManager.length;
for (uint256 i; i < permitVaultManagerLength; ++i) {
if (paramsPermitVaultManager[i].approved) {
IVaultManagerFunctions(paramsPermitVaultManager[i].vaultManager).permit(
paramsPermitVaultManager[i].owner,
address(this),
true,
paramsPermitVaultManager[i].deadline,
paramsPermitVaultManager[i].v,
paramsPermitVaultManager[i].r,
paramsPermitVaultManager[i].s
);
} else break;
}
mixer(paramsPermit, actions, data);
// Storing the index at which starting the iteration for revoking approvals in a variable would make the stack
// too deep
for (uint256 i; i < permitVaultManagerLength; ++i) {
if (!paramsPermitVaultManager[i].approved) {
IVaultManagerFunctions(paramsPermitVaultManager[i].vaultManager).permit(
paramsPermitVaultManager[i].owner,
address(this),
false,
paramsPermitVaultManager[i].deadline,
paramsPermitVaultManager[i].v,
paramsPermitVaultManager[i].r,
paramsPermitVaultManager[i].s
);
}
}
}
receive() external payable {}
// ===================== INTERNAL ACTION-RELATED FUNCTIONS =====================
/// @notice Wraps the native token of a chain to its wrapped version
/// @dev It can be used for ETH to wETH or MATIC to wMATIC
/// @dev The amount to wrap is to be specified in the `msg.value`
function _wrapNative() internal virtual returns (uint256) {
_getNativeWrapper().deposit{ value: msg.value }();
return msg.value;
}
/// @notice Unwraps the wrapped version of a token to the native chain token
/// @dev It can be used for wETH to ETH or wMATIC to MATIC
function _unwrapNative(uint256 minAmountOut, address to) internal virtual returns (uint256 amount) {
amount = _getNativeWrapper().balanceOf(address(this));
_slippageCheck(amount, minAmountOut);
if (amount != 0) {
_getNativeWrapper().withdraw(amount);
_safeTransferNative(to, amount);
}
return amount;
}
/// @notice Internal version of the `claimRewards` function
/// @dev If the caller wants to send the rewards to another account than `gaugeUser`, it first needs to
/// call `set_rewards_receiver(otherAccount)` on each `liquidityGauge`
function _claimRewards(address gaugeUser, address[] memory liquidityGauges) internal virtual {
uint256 gaugesLength = liquidityGauges.length;
for (uint256 i; i < gaugesLength; ++i) {
ILiquidityGauge(liquidityGauges[i]).claim_rewards(gaugeUser);
}
}
/// @notice Allows to compose actions on a `VaultManager` (Angle Protocol Borrowing module)
/// @param vaultManager Address of the vault to perform actions on
/// @param actionsBorrow Actions type to perform on the vaultManager
/// @param dataBorrow Data needed for each actions
/// @param to Address to send the funds to
/// @param who Swapper address to handle repayments
/// @param repayData Bytes to use at the discretion of the `msg.sender`
function _angleBorrower(
address vaultManager,
ActionBorrowType[] memory actionsBorrow,
bytes[] memory dataBorrow,
address to,
address who,
bytes memory repayData
) internal virtual returns (PaymentData memory paymentData) {
return IVaultManagerFunctions(vaultManager).angle(actionsBorrow, dataBorrow, msg.sender, to, who, repayData);
}
/// @notice Sweeps tokens from the router contract
/// @param tokenOut Token to sweep
/// @param minAmountOut Minimum amount of tokens to recover
/// @param to Address to which tokens should be sent
function _sweep(
address tokenOut,
uint256 minAmountOut,
address to
) internal virtual {
uint256 balanceToken = IERC20(tokenOut).balanceOf(address(this));
_slippageCheck(balanceToken, minAmountOut);
if (balanceToken != 0) {
IERC20(tokenOut).safeTransfer(to, balanceToken);
}
}
/// @notice Uses an external swapper
/// @param swapper Contracts implementing the logic of the swap
/// @param inToken Token used to do the swap
/// @param outToken Token wanted
/// @param outTokenRecipient Address who should have at the end of the swap at least `outTokenOwed`
/// @param outTokenOwed Minimal amount for the `outTokenRecipient`
/// @param inTokenObtained Amount of `inToken` used for the swap
/// @param data Additional info for the specific swapper
function _swapper(
ISwapper swapper,
IERC20 inToken,
IERC20 outToken,
address outTokenRecipient,
uint256 outTokenOwed,
uint256 inTokenObtained,
bytes memory data
) internal {
swapper.swap(inToken, outToken, outTokenRecipient, outTokenOwed, inTokenObtained, data);
}
/// @notice Swaps an inToken to another token via 1Inch Router
/// @param payload Bytes needed for 1Inch router to process the swap
/// @dev The `payload` given is expected to be obtained from 1Inch API
function _swapOn1Inch(
IERC20 inToken,
uint256 minAmountOut,
bytes memory payload
) internal returns (uint256 amountOut) {
// Approve transfer to the `oneInch` address
// Since this router is supposed to be a trusted contract, we can leave the allowance to the token
address oneInchRouter = oneInch;
_changeAllowance(IERC20(inToken), oneInchRouter, type(uint256).max);
//solhint-disable-next-line
(bool success, bytes memory result) = oneInchRouter.call(payload);
if (!success) _revertBytes(result);
amountOut = abi.decode(result, (uint256));
_slippageCheck(amountOut, minAmountOut);
}
/// @notice Mints `shares` from an ERC4626 contract
/// @param savingsRate ERC4626 to mint shares from
/// @param shares Amount of shares to mint from the contract
/// @param to Address to which shares should be sent
/// @param maxAmountIn Max amount of assets used to mint
/// @return amountIn Amount of assets used to mint by `to`
function _mint4626(
IERC4626 savingsRate,
uint256 shares,
address to,
uint256 maxAmountIn
) internal returns (uint256 amountIn) {
_slippageCheck(maxAmountIn, (amountIn = savingsRate.mint(shares, to)));
}
/// @notice Deposits `amount` to an ERC4626 contract
/// @param savingsRate The ERC4626 to deposit assets to
/// @param amount Amount of assets to deposit
/// @param to Address to which shares should be sent
/// @param minSharesOut Minimum amount of shares that `to` should received
/// @return sharesOut Amount of shares received by `to`
function _deposit4626(
IERC4626 savingsRate,
uint256 amount,
address to,
uint256 minSharesOut
) internal returns (uint256 sharesOut) {
_slippageCheck(sharesOut = savingsRate.deposit(amount, to), minSharesOut);
}
/// @notice Same as _deposit4626 but with the ability to specify a referring address
function _deposit4626Referral(
IERC4626 savingsRate,
uint256 amount,
address to,
uint256 minSharesOut,
address referrer
) internal returns (uint256 sharesOut) {
sharesOut = _deposit4626(savingsRate, amount, to, minSharesOut);
emit ReferredDeposit(msg.sender, to, amount, sharesOut, address(savingsRate), referrer);
}
/// @notice Withdraws `amount` from an ERC4626 contract
/// @param savingsRate ERC4626 to withdraw assets from
/// @param amount Amount of assets to withdraw
/// @param to Destination of assets
/// @param maxSharesOut Maximum amount of shares that should be burnt in the operation
/// @return sharesOut Amount of shares burnt
function _withdraw4626(
IERC4626 savingsRate,
uint256 amount,
address to,
uint256 maxSharesOut
) internal returns (uint256 sharesOut) {
_slippageCheck(maxSharesOut, sharesOut = savingsRate.withdraw(amount, to, msg.sender));
}
/// @notice Redeems `shares` from an ERC4626 contract
/// @param savingsRate ERC4626 to redeem shares from
/// @param shares Amount of shares to redeem
/// @param to Destination of assets
/// @param minAmountOut Minimum amount of assets that `to` should receive in the redemption process
/// @return amountOut Amount of assets received by `to`
function _redeem4626(
IERC4626 savingsRate,
uint256 shares,
address to,
uint256 minAmountOut
) internal returns (uint256 amountOut) {
_slippageCheck(amountOut = savingsRate.redeem(shares, to, msg.sender), minAmountOut);
}
/// @notice Allows to perform some specific actions for a chain
function _chainSpecificAction(ActionType action, bytes calldata data) internal virtual {}
// ======================= VIRTUAL FUNCTIONS TO OVERRIDE =======================
/// @notice Gets the official wrapper of the native token on a chain (like wETH on Ethereum)
function _getNativeWrapper() internal pure virtual returns (IWETH9);
// ============================ GOVERNANCE FUNCTION ============================
/// @notice Checks whether the `msg.sender` has the governor role or the guardian role
modifier onlyGovernorOrGuardian() {
if (!core.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();
_;
}
/// @notice Sets a new `core` contract
function setCore(ICoreBorrow _core) external {
if (!core.isGovernor(msg.sender) || !_core.isGovernor(msg.sender)) revert NotGovernor();
core = ICoreBorrow(_core);
}
/// @notice Changes allowances for different tokens
/// @param tokens Addresses of the tokens to allow
/// @param spenders Addresses to allow transfer
/// @param amounts Amounts to allow
function changeAllowance(
IERC20[] calldata tokens,
address[] calldata spenders,
uint256[] calldata amounts
) external onlyGovernorOrGuardian {
uint256 tokensLength = tokens.length;
if (tokensLength != spenders.length || tokensLength != amounts.length) revert IncompatibleLengths();
for (uint256 i; i < tokensLength; ++i) {
_changeAllowance(tokens[i], spenders[i], amounts[i]);
}
}
/// @notice Sets a new router variable
function setRouter(address router, uint8 who) external onlyGovernorOrGuardian {
if (router == address(0)) revert ZeroAddress();
if (who == 0) uniswapV3Router = IUniswapV3Router(router);
else oneInch = router;
}
// ========================= INTERNAL UTILITY FUNCTIONS ========================
/// @notice Changes allowance of this contract for a given token
/// @param token Address of the token to change allowance
/// @param spender Address to change the allowance of
/// @param amount Amount allowed
function _changeAllowance(
IERC20 token,
address spender,
uint256 amount
) internal {
uint256 currentAllowance = token.allowance(address(this), spender);
// In case `currentAllowance < type(uint256).max / 2` and we want to increase it:
// Do nothing (to handle tokens that need reapprovals to 0 and save gas)
if (currentAllowance < amount && currentAllowance < type(uint256).max / 2) {
token.safeIncreaseAllowance(spender, amount - currentAllowance);
} else if (currentAllowance > amount) {
token.safeDecreaseAllowance(spender, currentAllowance - amount);
}
}
/// @notice Transfer amount of the native token to the `to` address
/// @dev Forked from Solmate: https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol
function _safeTransferNative(address to, uint256 amount) internal {
bool success;
//solhint-disable-next-line
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
if (!success) revert TransferFailed();
}
/// @notice Parses the actions submitted to the router contract to interact with a `VaultManager` and makes sure that
/// the calling address is well approved for all the vaults with which it is interacting
/// @dev If such check was not made, we could end up in a situation where an address has given an approval for all its
/// vaults to the router contract, and another address takes advantage of this to instruct actions on these other vaults
/// to the router: it is hence super important for the router to pay attention to the fact that the addresses interacting
/// with a vault are approved for this vault
function _parseVaultIDs(
ActionBorrowType[] memory actionsBorrow,
bytes[] memory dataBorrow,
address vaultManager,
address collateral
) internal view returns (bytes[] memory) {
uint256 actionsBorrowLength = actionsBorrow.length;
uint256[] memory vaultIDsToCheckOwnershipOf = new uint256[](actionsBorrowLength);
bool createVaultAction;
uint256 lastVaultID;
uint256 vaultIDLength;
for (uint256 i; i < actionsBorrowLength; ++i) {
uint256 vaultID;
// If there is a `createVault` action, the router should not worry about looking at
// next vaultIDs given equal to 0
if (actionsBorrow[i] == ActionBorrowType.createVault) {
createVaultAction = true;
continue;
// If the action is a `addCollateral` action, we should check whether a max amount was given to end up adding
// as collateral the full contract balance
} else if (actionsBorrow[i] == ActionBorrowType.addCollateral) {
uint256 amount;
(vaultID, amount) = abi.decode(dataBorrow[i], (uint256, uint256));
if (amount == type(uint256).max)
dataBorrow[i] = abi.encode(vaultID, IERC20(collateral).balanceOf(address(this)));
continue;
// There are different ways depending on the action to find the `vaultID` to parse
} else if (
actionsBorrow[i] == ActionBorrowType.removeCollateral || actionsBorrow[i] == ActionBorrowType.borrow
) {
(vaultID, ) = abi.decode(dataBorrow[i], (uint256, uint256));
} else if (actionsBorrow[i] == ActionBorrowType.closeVault) {
vaultID = abi.decode(dataBorrow[i], (uint256));
} else if (actionsBorrow[i] == ActionBorrowType.getDebtIn) {
(vaultID, , , ) = abi.decode(dataBorrow[i], (uint256, address, uint256, uint256));
} else continue;
// If we need to add a null `vaultID`, we look at the `vaultIDCount` in the `VaultManager`
// if there has not been any specific action
if (vaultID == 0) {
if (createVaultAction) {
continue;
} else {
// If we haven't stored the last `vaultID`, we need to fetch it
if (lastVaultID == 0) {
lastVaultID = IVaultManagerStorage(vaultManager).vaultIDCount();
}
vaultID = lastVaultID;
}
}
// Check if this `vaultID` has already been verified
for (uint256 j; j < vaultIDLength; ++j) {
if (vaultIDsToCheckOwnershipOf[j] == vaultID) {
// If yes, we continue to the next iteration
continue;
}
}
// Verify this new `vaultID` and add it to the list
if (!IVaultManagerFunctions(vaultManager).isApprovedOrOwner(msg.sender, vaultID)) {
revert NotApprovedOrOwner();
}
vaultIDsToCheckOwnershipOf[vaultIDLength] = vaultID;
vaultIDLength += 1;
}
return dataBorrow;
}
/// @notice Checks whether the amount obtained during a swap is not too small
function _slippageCheck(uint256 amount, uint256 thresholdAmount) internal pure {
if (amount < thresholdAmount) revert TooSmallAmountOut();
}
/// @notice Internal function used for error handling
function _revertBytes(bytes memory errMsg) internal pure {
if (errMsg.length != 0) {
//solhint-disable-next-line
assembly {
revert(add(32, errMsg), mload(errMsg))
}
}
revert InvalidReturnMessage();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*
* _Available since v4.7._
*/
interface IERC4626 is IERC20, IERC20Metadata {
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
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface IUniswapV3Router {
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
}
/// @title Router for price estimation functionality
/// @notice Functions for getting the price of one token with respect to another using Uniswap V2
/// @dev This interface is only used for non critical elements of the protocol
interface IUniswapV2Router {
/// @notice Given an input asset amount, returns the maximum output amount of the
/// other asset (accounting for fees) given reserves.
/// @param path Addresses of the pools used to get prices
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function swapExactTokensForTokens(
uint256 swapAmount,
uint256 minExpected,
address[] calldata path,
address receiver,
uint256 swapDeadline
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Interface for WETH9
interface IWETH9 is IERC20 {
/// @notice Deposit ether to get wrapped ether
function deposit() external payable;
/// @notice Withdraw wrapped ether to get ether
function withdraw(uint256) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
/// @title ICoreBorrow
/// @author Angle Core Team
/// @notice Interface for the `CoreBorrow` contract
interface ICoreBorrow {
/// @notice Checks whether an address is governor of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GOVERNOR_ROLE` or not
function isGovernor(address admin) external view returns (bool);
/// @notice Checks whether an address is governor or a guardian of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GUARDIAN_ROLE` or not
/// @dev Governance should make sure when adding a governor to also give this governor the guardian
/// role by calling the `addGovernor` function
function isGovernorOrGuardian(address admin) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IDepositWithReferral
/// @author Angle Core Team
/// @notice Interface for Angle routing contract to notably deposit into ERC4626 with a referral address
interface IDepositWithReferral {
/// @notice Deposits `amount` of `token` into an ERC4626 `savings` contract (with `token` as an asset)
/// @param minSharesOut Minimum amount of shares of the ERC4626 the deposit should return. If less is
/// obtained, the function reverts
/// @param referrer Address which referred `msg.sender` to deposit into `savings`. Any address can be entered
/// and the referrer address has no storage implication, it just changes the event emitted by this contract
/// when a deposit takes place
/// @dev This function is a wrapper on top of the base `deposit` function of ERC4626 with the ability to
/// specify a referring address (`referrer`) as well as a slippage parameter (`minSharesOut`)
function deposit4626Referral(
address token,
address savings,
uint256 amount,
address to,
uint256 minSharesOut,
address referrer
) external returns (uint256 sharesOut);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
interface ILiquidityGauge {
// solhint-disable-next-line
function staking_token() external returns (address stakingToken);
// solhint-disable-next-line
function deposit_reward_token(address _rewardToken, uint256 _amount) external;
function deposit(
uint256 _value,
address _addr,
// solhint-disable-next-line
bool _claim_rewards
) external;
// solhint-disable-next-line
function claim_rewards(address _addr) external;
// solhint-disable-next-line
function claim_rewards(address _addr, address _receiver) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
/// @title ISwapper
/// @author Angle Core Team
/// @notice Interface for a generic swapper, that supports swaps of higher complexity than aggregators
interface ISwapper {
function swap(
IERC20 inToken,
IERC20 outToken,
address outTokenRecipient,
uint256 outTokenOwed,
uint256 inTokenObtained,
bytes memory data
) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ITreasury.sol";
// ========================= Key Structs and Enums =============================
/// @notice Data to track during a series of action the amount to give or receive in stablecoins and collateral
/// to the caller or associated addresses
struct PaymentData {
// Stablecoin amount the contract should give
uint256 stablecoinAmountToGive;
// Stablecoin amount owed to the contract
uint256 stablecoinAmountToReceive;
// Collateral amount the contract should give
uint256 collateralAmountToGive;
// Collateral amount owed to the contract
uint256 collateralAmountToReceive;
}
/// @notice Data stored to track someone's loan (or equivalently called position)
struct Vault {
// Amount of collateral deposited in the vault
uint256 collateralAmount;
// Normalized value of the debt (that is to say of the stablecoins borrowed)
uint256 normalizedDebt;
}
/// @notice Actions possible when composing calls to the different entry functions proposed
enum ActionBorrowType {
createVault,
closeVault,
addCollateral,
removeCollateral,
repayDebt,
borrow,
getDebtIn,
permit
}
// ========================= Interfaces =============================
/// @title IVaultManagerFunctions
/// @author Angle Core Team
/// @notice Interface for the `VaultManager` contract
/// @dev This interface only contains functions of the contract which are called by other contracts
/// of this module (without getters)
interface IVaultManagerFunctions {
/// @notice Allows composability between calls to the different entry points of this module. Any user calling
/// this function can perform any of the allowed actions in the order of their choice
/// @param actions Set of actions to perform
/// @param datas Data to be decoded for each action: it can include like the `vaultID` or the
/// @param from Address from which stablecoins will be taken if one action includes burning stablecoins. This address
/// should either be the `msg.sender` or be approved by the latter
/// @param to Address to which stablecoins and/or collateral will be sent in case of
/// @return paymentData Struct containing the final transfers executed
/// @dev This function is optimized to reduce gas cost due to payment from or to the user and that expensive calls
/// or computations (like `oracleValue`) are done only once
function angle(
ActionBorrowType[] memory actions,
bytes[] memory datas,
address from,
address to
) external payable returns (PaymentData memory paymentData);
/// @notice Allows composability between calls to the different entry points of this module. Any user calling
/// this function can perform any of the allowed actions in the order of their choice
/// @param actions Set of actions to perform
/// @param datas Data to be decoded for each action: it can include like the `vaultID` or the
/// @param from Address from which stablecoins will be taken if one action includes burning stablecoins. This address
/// should either be the `msg.sender` or be approved by the latter
/// @param to Address to which stablecoins and/or collateral will be sent in case of
/// @param who Address of the contract to handle in case of repayment of stablecoins from received collateral
/// @param repayData Data to pass to the repayment contract in case of
/// @return paymentData Struct containing the final transfers executed
/// @dev This function is optimized to reduce gas cost due to payment from or to the user and that expensive calls
/// or computations (like `oracleValue`) are done only once
function angle(
ActionBorrowType[] memory actions,
bytes[] memory datas,
address from,
address to,
address who,
bytes memory repayData
) external payable returns (PaymentData memory paymentData);
/// @notice Checks whether a given address is approved for a vault or owns this vault
/// @param spender Address for which vault ownership should be checked
/// @param vaultID ID of the vault to check
/// @return Whether the `spender` address owns or is approved for `vaultID`
function isApprovedOrOwner(address spender, uint256 vaultID) external view returns (bool);
/// @notice Allows an address to give or revoke approval for all its vaults to another address
/// @param owner Address signing the permit and giving (or revoking) its approval for all the controlled vaults
/// @param spender Address to give approval to
/// @param approved Whether to give or revoke the approval
/// @param deadline Deadline parameter for the signature to be valid
/// @dev The `v`, `r`, and `s` parameters are used as signature data
function permit(
address owner,
address spender,
bool approved,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
/// @title IVaultManagerStorage
/// @author Angle Core Team
/// @notice Interface for the `VaultManager` contract
/// @dev This interface contains getters of the contract's public variables used by other contracts
/// of this module
interface IVaultManagerStorage {
/// @notice Reference to the `treasury` contract handling this `VaultManager`
function treasury() external view returns (ITreasury);
/// @notice Reference to the collateral handled by this `VaultManager`
function collateral() external view returns (IERC20);
/// @notice ID of the last vault created. The `vaultIDCount` variables serves as a counter to generate a unique
/// `vaultID` for each vault: it is like `tokenID` in basic ERC721 contracts
function vaultIDCount() external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;
/// @title ITreasury
/// @author Angle Core Team
/// @notice Interface for the `Treasury` contract
/// @dev This interface only contains functions of the `Treasury` which are called by other contracts
/// of this module
interface ITreasury {
/// @notice Checks whether a given address has well been initialized in this contract
/// as a `VaultManager``
/// @param _vaultManager Address to check
/// @return Whether the address has been initialized or not
function isVaultManager(address _vaultManager) external view returns (bool);
}{
"remappings": [
"@chainlink/=node_modules/@chainlink/",
"@ensdomains/=node_modules/@ensdomains/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@uniswap/=node_modules/@uniswap/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"utils/=lib/utils/",
"base64-sol/=node_modules/base64-sol/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"lz/=lib/utils/lib/solidity-examples/contracts/",
"openzeppelin-contracts/=lib/utils/lib/openzeppelin-contracts/",
"oz/=lib/utils/lib/openzeppelin-contracts/contracts/",
"solidity-examples/=lib/utils/lib/solidity-examples/contracts/",
"solidity-stringutils/=lib/utils/lib/solidity-stringutils/",
"stringutils/=lib/utils/lib/solidity-stringutils/src/"
],
"optimizer": {
"enabled": true,
"runs": 100
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"IncompatibleLengths","type":"error"},{"inputs":[],"name":"InvalidReturnMessage","type":"error"},{"inputs":[],"name":"NotApprovedOrOwner","type":"error"},{"inputs":[],"name":"NotGovernor","type":"error"},{"inputs":[],"name":"NotGovernorOrGuardian","type":"error"},{"inputs":[],"name":"TooSmallAmountOut","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"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"},{"indexed":true,"internalType":"address","name":"savings","type":"address"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"}],"name":"ReferredDeposit","type":"event"},{"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"spenders","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"changeAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"contract ICoreBorrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"savings","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSharesOut","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"deposit4626Referral","outputs":[{"internalType":"uint256","name":"sharesOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"address","name":"_uniswapRouter","type":"address"},{"internalType":"address","name":"_oneInch","type":"address"}],"name":"initializeRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","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"}],"internalType":"struct PermitType[]","name":"paramsPermit","type":"tuple[]"},{"internalType":"enum ActionType[]","name":"actions","type":"uint8[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"mixer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vaultManager","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitVaultManagerType[]","name":"paramsPermitVaultManager","type":"tuple[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","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"}],"internalType":"struct PermitType[]","name":"paramsPermit","type":"tuple[]"},{"internalType":"enum ActionType[]","name":"actions","type":"uint8[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"mixerVaultManagerPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"oneInch","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ICoreBorrow","name":"_core","type":"address"}],"name":"setCore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint8","name":"who","type":"uint8"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV3Router","outputs":[{"internalType":"contract IUniswapV3Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b50600054610100900460ff16158080156100315750600054600160ff909116105b8061004b5750303b15801561004b575060005460ff166001145b6100b25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156100d5576000805461ff0019166101001790555b801561011b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b506135ba8061012b6000396000f3fe6080604052600436106100955760003560e01c80638000963011610059578063800096301461015a57806383f1d6811461017a578063848c48da1461019a578063b82c4dc1146101ad578063f2f4eb26146101cd57600080fd5b8063045c08d5146100a15780632c76d7a6146100d757806340c7c4ed146100f757806342860d4b1461012557806359856d561461014757600080fd5b3661009c57005b600080fd5b3480156100ad57600080fd5b506002546100c1906001600160a01b031681565b6040516100ce919061262d565b60405180910390f35b3480156100e357600080fd5b506001546100c1906001600160a01b031681565b34801561010357600080fd5b50610117610112366004612659565b6101f3565b6040519081526020016100ce565b34801561013157600080fd5b506101456101403660046126c9565b61022f565b005b6101456101553660046128f2565b6103b8565b34801561016657600080fd5b50610145610175366004612a8d565b61067a565b34801561018657600080fd5b50610145610195366004612aaa565b6107ae565b6101456101a8366004612adf565b6108b4565b3480156101b957600080fd5b506101456101c8366004612b7d565b611434565b3480156101d957600080fd5b506000546100c1906201000090046001600160a01b031681565b600061020a6001600160a01b038816333088611577565b61021787876000196115e2565b61022486868686866116c0565b979650505050505050565b600054610100900460ff161580801561024f5750600054600160ff909116105b806102695750303b158015610269575060005460ff166001145b6102d15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156102f4576000805461ff0019166101001790555b6001600160a01b03841661031b5760405163d92e233d60e01b815260040160405180910390fd5b600080546001600160a01b03808716620100000262010000600160b01b031990921691909117909155600180548583166001600160a01b031991821617909155600280549285169290911691909117905580156103b2576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b855160005b81811015610513578781815181106103d7576103d7612c02565b60200260200101516040015115610506578781815181106103fa576103fa612c02565b6020026020010151600001516001600160a01b031663f51cc7dd89838151811061042657610426612c02565b6020026020010151602001513060018c868151811061044757610447612c02565b6020026020010151606001518d878151811061046557610465612c02565b6020026020010151608001518e888151811061048357610483612c02565b602002602001015160a001518f89815181106104a1576104a1612c02565b602002602001015160c001516040518863ffffffff1660e01b81526004016104cf9796959493929190612c18565b600060405180830381600087803b1580156104e957600080fd5b505af11580156104fd573d6000803e3d6000fd5b5050505061050b565b610513565b6001016103bd565b5061052186868686866108b4565b60005b818110156106705787818151811061053e5761053e612c02565b6020026020010151604001516106685787818151811061056057610560612c02565b6020026020010151600001516001600160a01b031663f51cc7dd89838151811061058c5761058c612c02565b6020026020010151602001513060008c86815181106105ad576105ad612c02565b6020026020010151606001518d87815181106105cb576105cb612c02565b6020026020010151608001518e88815181106105e9576105e9612c02565b602002602001015160a001518f898151811061060757610607612c02565b602002602001015160c001516040518863ffffffff1660e01b81526004016106359796959493929190612c18565b600060405180830381600087803b15801561064f57600080fd5b505af1158015610663573d6000803e3d6000fd5b505050505b600101610524565b5050505050505050565b600054604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906106af90339060040161262d565b602060405180830381865afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f09190612c59565b15806107665750604051631c86b03760e31b81526001600160a01b0382169063e43581b89061072390339060040161262d565b602060405180830381865afa158015610740573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107649190612c59565b155b1561078457604051633b8d9d7560e21b815260040160405180910390fd5b600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b60005460405163521d4de960e01b8152620100009091046001600160a01b03169063521d4de9906107e390339060040161262d565b602060405180830381865afa158015610800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108249190612c59565b61084157604051632678482f60e21b815260040160405180910390fd5b6001600160a01b0382166108685760405163d92e233d60e01b815260040160405180910390fd5b8060ff1660000361089457600180546001600160a01b0384166001600160a01b03199091161790555050565b600280546001600160a01b0319166001600160a01b0384161790555b5050565b845160005b81811015610a34578681815181106108d3576108d3612c02565b6020026020010151600001516001600160a01b031663d505accf8883815181106108ff576108ff612c02565b602002602001015160200151308a858151811061091e5761091e612c02565b6020026020010151604001518b868151811061093c5761093c612c02565b6020026020010151606001518c878151811061095a5761095a612c02565b6020026020010151608001518d888151811061097857610978612c02565b602002602001015160a001518e898151811061099657610996612c02565b602090810291909101015160c001516040516001600160e01b031960e08a901b1681526001600160a01b0397881660048201529690951660248701526044860193909352606485019190915260ff16608484015260a483015260c482015260e401600060405180830381600087803b158015610a1157600080fd5b505af1158015610a25573d6000803e3d6000fd5b505050508060010190506108b9565b508360005b81811015610670576000878783818110610a5557610a55612c02565b9050602002016020810190610a6a9190612c8c565b601b811115610a7b57610a7b612c76565b03610b52576000806000878785818110610a9757610a97612c02565b9050602002810190610aa99190612cad565b810190610ab69190612cfe565b9250925092506000198103610b35576040516370a0823160e01b81526001600160a01b038416906370a0823190610af190339060040161262d565b602060405180830381865afa158015610b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b329190612d3f565b90505b610b4a6001600160a01b038416338484611577565b50505061142c565b6001878783818110610b6657610b66612c02565b9050602002016020810190610b7b9190612c8c565b601b811115610b8c57610b8c612c76565b03610b9f57610b9961172e565b5061142c565b6002878783818110610bb357610bb3612c02565b9050602002016020810190610bc89190612c8c565b601b811115610bd957610bd9612c76565b03610c2057600080868684818110610bf357610bf3612c02565b9050602002810190610c059190612cad565b810190610c129190612d58565b91509150610b4a828261179e565b6003878783818110610c3457610c34612c02565b9050602002016020810190610c499190612c8c565b601b811115610c5a57610c5a612c76565b03610ca6576000806000878785818110610c7657610c76612c02565b9050602002810190610c889190612cad565b810190610c959190612d88565b925092509250610b4a8383836118a0565b6004878783818110610cba57610cba612c02565b9050602002016020810190610ccf9190612c8c565b601b811115610ce057610ce0612c76565b03610cf657478015610b9957610b993382611936565b6006878783818110610d0a57610d0a612c02565b9050602002016020810190610d1f9190612c8c565b601b811115610d3057610d30612c76565b03610d85576000806000878785818110610d4c57610d4c612c02565b9050602002810190610d5e9190612cad565b810190610d6b9190612e2e565b925092509250610d7c838383611962565b5050505061142c565b6007878783818110610d9957610d99612c02565b9050602002016020810190610dae9190612c8c565b601b811115610dbf57610dbf612c76565b03610e0d57600080868684818110610dd957610dd9612c02565b9050602002810190610deb9190612cad565b810190610df89190612e86565b91509150610e068282611a18565b505061142c565b6009878783818110610e2157610e21612c02565b9050602002016020810190610e369190612c8c565b601b811115610e4757610e47612c76565b03610ecc5760008060008060008060008b8b89818110610e6957610e69612c02565b9050602002810190610e7b9190612cad565b810190610e889190613026565b9650965096509650965096509650610ea28383888a611aa7565b9150610eb187876000196115e2565b610ebf868484888886611f56565b505050505050505061142c565b600a878783818110610ee057610ee0612c02565b9050602002016020810190610ef59190612c8c565b601b811115610f0657610f06612c76565b03610f705760008060008060008060008b8b89818110610f2857610f28612c02565b9050602002810190610f3a9190612cad565b810190610f4791906130fc565b9650965096509650965096509650610f6487878787878787611ffa565b5050505050505061142c565b600b878783818110610f8457610f84612c02565b9050602002016020810190610f999190612c8c565b601b811115610faa57610faa612c76565b03611016576000806000806000898987818110610fc957610fc9612c02565b9050602002810190610fdb9190612cad565b810190610fe8919061317b565b94509450945094509450610fff85856000196115e2565b61100b8484848461206b565b50505050505061142c565b600c87878381811061102a5761102a612c02565b905060200201602081019061103f9190612c8c565b601b81111561105057611050612c76565b0361112a57600080600080600089898781811061106f5761106f612c02565b90506020028101906110819190612cad565b81019061108e919061317b565b945094509450945094506000198303611111576040516370a0823160e01b81526001600160a01b038616906370a08231906110cd90309060040161262d565b602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110e9190612d3f565b92505b61111e85856000196115e2565b61100b848484846120f1565b601b87878381811061113e5761113e612c02565b90506020020160208101906111539190612c8c565b601b81111561116457611164612c76565b03611242576000806000806000808a8a8881811061118457611184612c02565b90506020028101906111969190612cad565b8101906111a39190612659565b9550955095509550955095506000198403611228576040516370a0823160e01b81526001600160a01b038716906370a08231906111e490309060040161262d565b602060405180830381865afa158015611201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112259190612d3f565b93505b61123586866000196115e2565b610f6485858585856116c0565b600d87878381811061125657611256612c02565b905060200201602081019061126b9190612c8c565b601b81111561127c5761127c612c76565b0361134f5760008060008088888681811061129957611299612c02565b90506020028101906112ab9190612cad565b8101906112b891906131d6565b93509350935093506000198303611339576040516370a0823160e01b81526001600160a01b038516906370a08231906112f590339060040161262d565b602060405180830381865afa158015611312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113369190612d3f565b92505b61134584848484612175565b505050505061142c565b600e87878381811061136357611363612c02565b90506020020160208101906113789190612c8c565b601b81111561138957611389612c76565b036113d9576000806000808888868181106113a6576113a6612c02565b90506020028101906113b89190612cad565b8101906113c591906131d6565b9350935093509350611345848484846121aa565b61142c8787838181106113ee576113ee612c02565b90506020020160208101906114039190612c8c565b86868481811061141557611415612c02565b90506020028101906114279190612cad565b505050565b600101610a39565b60005460405163521d4de960e01b8152620100009091046001600160a01b03169063521d4de99061146990339060040161262d565b602060405180830381865afa158015611486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114aa9190612c59565b6114c757604051632678482f60e21b815260040160405180910390fd5b8483811415806114d75750808214155b156114f5576040516346282e8d60e01b815260040160405180910390fd5b60005b818110156106705761156f88888381811061151557611515612c02565b905060200201602081019061152a9190612a8d565b87878481811061153c5761153c612c02565b90506020020160208101906115519190612a8d565b86868581811061156357611563612c02565b905060200201356115e2565b6001016114f8565b6040516001600160a01b03808516602483015283166044820152606481018290526103b29085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526121e0565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e90611613903090879060040161321e565b602060405180830381865afa158015611630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116549190612d3f565b90508181108015611670575061166d600260001961324e565b81105b1561169957611694836116838385613270565b6001600160a01b03871691906122b2565b6103b2565b818111156103b2576103b2836116af8484613270565b6001600160a01b038716919061234f565b60006116ce868686866120f1565b60408051338152602081018890529081018290529091506001600160a01b0380841691888216918716907ff0abe475665c1088274490f21db8d3d3351d565d49d5222cc54656fba17f49119060600160405180910390a495945050505050565b600073e5d7c2a44ffddf6b295a15c148167daaaf5cf34f6001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561177f57600080fd5b505af1158015611793573d6000803e3d6000fd5b505050505034905090565b6040516370a0823160e01b815260009073e5d7c2a44ffddf6b295a15c148167daaaf5cf34f906370a08231906117d890309060040161262d565b602060405180830381865afa1580156117f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118199190612d3f565b90506118258184612452565b801561189a57604051632e1a7d4d60e01b81526004810182905273e5d7c2a44ffddf6b295a15c148167daaaf5cf34f90632e1a7d4d90602401600060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b5050505061189a8282611936565b92915050565b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906118cf90309060040161262d565b602060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612d3f565b905061191c8184612452565b80156103b2576103b26001600160a01b0385168383612473565b600080600080600085875af1905080611427576040516312171d8360e31b815260040160405180910390fd5b6002546000906001600160a01b031661197e85826000196115e2565b600080826001600160a01b03168560405161199991906132a7565b6000604051808303816000865af19150503d80600081146119d6576040519150601f19603f3d011682016040523d82523d6000602084013e6119db565b606091505b5091509150816119ee576119ee81612492565b80806020019051810190611a029190612d3f565b9350611a0e8487612452565b5050509392505050565b805160005b818110156103b257828181518110611a3757611a37612c02565b60200260200101516001600160a01b03166384e9bd7e856040518263ffffffff1660e01b8152600401611a6a919061262d565b600060405180830381600087803b158015611a8457600080fd5b505af1158015611a98573d6000803e3d6000fd5b50505050806001019050611a1d565b83516060906000816001600160401b03811115611ac657611ac6612714565b604051908082528060200260200182016040528015611aef578160200160208202803683370190505b5090506000806000805b85811015611f44576000808c8381518110611b1657611b16612c02565b60200260200101516007811115611b2f57611b2f612c76565b03611b3e576001945050611f3c565b60028c8381518110611b5257611b52612c02565b60200260200101516007811115611b6b57611b6b612c76565b03611c615760008b8381518110611b8457611b84612c02565b6020026020010151806020019051810190611b9f91906132c3565b909250905060018101611c5a576040516370a0823160e01b815282906001600160a01b038c16906370a0823190611bda90309060040161262d565b602060405180830381865afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1b9190612d3f565b6040805160208101939093528201526060016040516020818303038152906040528c8481518110611c4e57611c4e612c02565b60200260200101819052505b5050611f3c565b60038c8381518110611c7557611c75612c02565b60200260200101516007811115611c8e57611c8e612c76565b1480611cc4575060058c8381518110611ca957611ca9612c02565b60200260200101516007811115611cc257611cc2612c76565b145b15611cfe578a8281518110611cdb57611cdb612c02565b6020026020010151806020019051810190611cf691906132c3565b509050611dd5565b60018c8381518110611d1257611d12612c02565b60200260200101516007811115611d2b57611d2b612c76565b03611d64578a8281518110611d4257611d42612c02565b6020026020010151806020019051810190611d5d9190612d3f565b9050611dd5565b60068c8381518110611d7857611d78612c02565b60200260200101516007811115611d9157611d91612c76565b03611dcf578a8281518110611da857611da8612c02565b6020026020010151806020019051810190611dc391906132e7565b50919250611dd5915050565b50611f3c565b80600003611e59578415611de95750611f3c565b83600003611e5657896001600160a01b0316633c2e941b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e539190612d3f565b93505b50825b60005b83811015611e825781878281518110611e7757611e77612c02565b505050600101611e5c565b5060405163430c208160e01b81526001600160a01b038b169063430c208190611eb19033908590600401613326565b602060405180830381865afa158015611ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef29190612c59565b611f0f5760405163390cdd9b60e21b815260040160405180910390fd5b80868481518110611f2257611f22612c02565b6020908102919091010152611f3860018461333f565b9250505b600101611af9565b5088955050505050505b949350505050565b611f816040518060800160405280600081526020016000815260200160008152602001600081525090565b604051631bd1f8d360e31b81526001600160a01b0388169063de8fc69890611fb7908990899033908a908a908a906004016133da565b6080604051808303816000875af1158015611fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610224919061349b565b60405163a5d4096b60e01b81526001600160a01b0388169063a5d4096b9061203090899089908990899089908990600401613504565b600060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b5050505050505050505050565b6040516394bf804d60e01b8152600481018490526001600160a01b038381166024830152600091611f4e918491908816906394bf804d906044015b6020604051808303816000875af11580156120c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e99190612d3f565b925082612452565b604051636e553f6560e01b8152600481018490526001600160a01b038381166024830152600091611f4e91871690636e553f65906044015b6020604051808303816000875af1158015612148573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216c9190612d3f565b91508183612452565b6000611f4e856001600160a01b031663ba0876528686336040518463ffffffff1660e01b815260040161212993929190613552565b6000611f4e82866001600160a01b031663b460af948787336040518463ffffffff1660e01b81526004016120a693929190613552565b6000612235826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124ba9092919063ffffffff16565b80519091501561142757808060200190518101906122539190612c59565b6114275760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102c8565b600081846001600160a01b031663dd62ed3e30866040518363ffffffff1660e01b81526004016122e392919061321e565b602060405180830381865afa158015612300573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123249190612d3f565b61232e919061333f565b90506103b28463095ea7b360e01b85846040516024016115ab929190613326565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e90612380903090879060040161321e565b602060405180830381865afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c19190612d3f565b9050818110156124255760405162461bcd60e51b815260206004820152602960248201527f5361666545524332303a2064656372656173656420616c6c6f77616e63652062604482015268656c6f77207a65726f60b81b60648201526084016102c8565b6040518282039061244b90869063095ea7b360e01b906115ab9088908690602401613326565b5050505050565b808210156108b05760405163a1aabbe160e01b815260040160405180910390fd5b6114278363a9059cbb60e01b84846040516024016115ab929190613326565b8051156124a157805181602001fd5b60405163ee418e3760e01b815260040160405180910390fd5b60606124c984846000856124d3565b90505b9392505050565b6060824710156125345760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102c8565b6001600160a01b0385163b61258b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102c8565b600080866001600160a01b031685876040516125a791906132a7565b60006040518083038185875af1925050503d80600081146125e4576040519150601f19603f3d011682016040523d82523d6000602084013e6125e9565b606091505b5091509150610224828286606083156126035750816124cc565b8251156126135782518084602001fd5b8160405162461bcd60e51b81526004016102c89190613571565b6001600160a01b0391909116815260200190565b6001600160a01b038116811461265657600080fd5b50565b60008060008060008060c0878903121561267257600080fd5b863561267d81612641565b9550602087013561268d81612641565b94506040870135935060608701356126a481612641565b92506080870135915060a08701356126bb81612641565b809150509295509295509295565b6000806000606084860312156126de57600080fd5b83356126e981612641565b925060208401356126f981612641565b9150604084013561270981612641565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171561274c5761274c612714565b60405290565b604051601f8201601f191681016001600160401b038111828210171561277a5761277a612714565b604052919050565b60006001600160401b0382111561279b5761279b612714565b5060051b60200190565b801515811461265657600080fd5b803560ff811681146127c457600080fd5b919050565b600082601f8301126127da57600080fd5b81356127ed6127e882612782565b612752565b80828252602082019150602060e0840286010192508583111561280f57600080fd5b602085015b8381101561289d5760e0818803121561282c57600080fd5b61283461272a565b813561283f81612641565b8152602082013561284f81612641565b60208201526040828101359082015260608083013590820152612874608083016127b3565b608082015260a0828101359082015260c08083013590820152835260209092019160e001612814565b5095945050505050565b60008083601f8401126128b957600080fd5b5081356001600160401b038111156128d057600080fd5b6020830191508360208260051b85010111156128eb57600080fd5b9250929050565b6000806000806000806080878903121561290b57600080fd5b86356001600160401b0381111561292157600080fd5b8701601f8101891361293257600080fd5b80356129406127e882612782565b80828252602082019150602060e0840285010192508b83111561296257600080fd5b6020840193505b828410156129fe5760e0848d03121561298157600080fd5b61298961272a565b843561299481612641565b815260208501356129a481612641565b602082015260408501356129b7816127a5565b6040820152606085810135908201526129d2608086016127b3565b608082015260a0858101359082015260c08086013590820152825260e090930192602090910190612969565b985050505060208701356001600160401b03811115612a1c57600080fd5b612a2889828a016127c9565b95505060408701356001600160401b03811115612a4457600080fd5b612a5089828a016128a7565b90955093505060608701356001600160401b03811115612a6f57600080fd5b612a7b89828a016128a7565b979a9699509497509295939492505050565b600060208284031215612a9f57600080fd5b81356124cc81612641565b60008060408385031215612abd57600080fd5b8235612ac881612641565b9150612ad6602084016127b3565b90509250929050565b600080600080600060608688031215612af757600080fd5b85356001600160401b03811115612b0d57600080fd5b612b19888289016127c9565b95505060208601356001600160401b03811115612b3557600080fd5b612b41888289016128a7565b90955093505060408601356001600160401b03811115612b6057600080fd5b612b6c888289016128a7565b969995985093965092949392505050565b60008060008060008060608789031215612b9657600080fd5b86356001600160401b03811115612bac57600080fd5b612bb889828a016128a7565b90975095505060208701356001600160401b03811115612bd757600080fd5b612be389828a016128a7565b90955093505060408701356001600160401b03811115612a6f57600080fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0397881681529590961660208601529215156040850152606084019190915260ff16608083015260a082015260c081019190915260e00190565b600060208284031215612c6b57600080fd5b81516124cc816127a5565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612c9e57600080fd5b8135601c81106124cc57600080fd5b6000808335601e19843603018112612cc457600080fd5b8301803591506001600160401b03821115612cde57600080fd5b6020019150368190038213156128eb57600080fd5b80356127c481612641565b600080600060608486031215612d1357600080fd5b8335612d1e81612641565b92506020840135612d2e81612641565b929592945050506040919091013590565b600060208284031215612d5157600080fd5b5051919050565b60008060408385031215612d6b57600080fd5b823591506020830135612d7d81612641565b809150509250929050565b600080600060608486031215612d9d57600080fd5b8335612da881612641565b925060208401359150604084013561270981612641565b600082601f830112612dd057600080fd5b81356001600160401b03811115612de957612de9612714565b612dfc601f8201601f1916602001612752565b818152846020838601011115612e1157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215612e4357600080fd5b8335612e4e81612641565b92506020840135915060408401356001600160401b03811115612e7057600080fd5b612e7c86828701612dbf565b9150509250925092565b60008060408385031215612e9957600080fd5b8235612ea481612641565b915060208301356001600160401b03811115612ebf57600080fd5b8301601f81018513612ed057600080fd5b8035612ede6127e882612782565b8082825260208201915060208360051b850101925087831115612f0057600080fd5b6020840193505b82841015612f2b578335612f1a81612641565b825260209384019390910190612f07565b809450505050509250929050565b600082601f830112612f4a57600080fd5b8135612f586127e882612782565b8082825260208201915060208360051b860101925085831115612f7a57600080fd5b602085015b8381101561289d57803560088110612f9657600080fd5b835260209283019201612f7f565b600082601f830112612fb557600080fd5b8135612fc36127e882612782565b8082825260208201915060208360051b860101925085831115612fe557600080fd5b602085015b8381101561289d5780356001600160401b0381111561300857600080fd5b613017886020838a0101612dbf565b84525060209283019201612fea565b600080600080600080600060e0888a03121561304157600080fd5b873561304c81612641565b965061305a60208901612cf3565b955061306860408901612cf3565b945061307660608901612cf3565b935060808801356001600160401b0381111561309157600080fd5b61309d8a828b01612f39565b93505060a08801356001600160401b038111156130b957600080fd5b6130c58a828b01612fa4565b92505060c08801356001600160401b038111156130e157600080fd5b6130ed8a828b01612dbf565b91505092959891949750929550565b600080600080600080600060e0888a03121561311757600080fd5b873561312281612641565b9650602088013561313281612641565b9550604088013561314281612641565b9450606088013561315281612641565b93506080880135925060a0880135915060c08801356001600160401b038111156130e157600080fd5b600080600080600060a0868803121561319357600080fd5b853561319e81612641565b945060208601356131ae81612641565b93506040860135925060608601356131c581612641565b949793965091946080013592915050565b600080600080608085870312156131ec57600080fd5b84356131f781612641565b935060208501359250604085013561320e81612641565b9396929550929360600135925050565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b60008261326b57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561189a5761189a613238565b60005b8381101561329e578181015183820152602001613286565b50506000910152565b600082516132b9818460208701613283565b9190910192915050565b600080604083850312156132d657600080fd5b505080516020909101519092909150565b600080600080608085870312156132fd57600080fd5b8451602086015190945061331081612641565b6040860151606090960151949790965092505050565b6001600160a01b03929092168252602082015260400190565b8082018082111561189a5761189a613238565b6000815180845261336a816020860160208601613283565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b838110156133ce57601f198584030188526133b8838351613352565b602098890198909350919091019060010161339c565b50909695505050505050565b60c08082528751908201819052600090602089019060e0840190835b818110156134325783516008811061341e57634e487b7160e01b600052602160045260246000fd5b8352602093840193909201916001016133f6565b50508381036020850152613446818a61337e565b91505061345e60408401886001600160a01b03169052565b6001600160a01b03861660608401526001600160a01b038516608084015282810360a084015261348e8185613352565b9998505050505050505050565b600060808284031280156134ae57600080fd5b50604051600090608081016001600160401b03811182821017156134d4576134d4612714565b60409081528451825260208086015190830152848101519082015260609384015193810193909352509092915050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c060a0820181905260009061354690830184613352565b98975050505050505050565b9283526001600160a01b03918216602084015216604082015260600190565b6020815260006124cc602083018461335256fea2646970667358221220af02a6830f3506091b8a99377aa49884c4255b6d2022f57bd3aa200ff85065be64736f6c634300081a0033
Deployed Bytecode
0x6080604052600436106100955760003560e01c80638000963011610059578063800096301461015a57806383f1d6811461017a578063848c48da1461019a578063b82c4dc1146101ad578063f2f4eb26146101cd57600080fd5b8063045c08d5146100a15780632c76d7a6146100d757806340c7c4ed146100f757806342860d4b1461012557806359856d561461014757600080fd5b3661009c57005b600080fd5b3480156100ad57600080fd5b506002546100c1906001600160a01b031681565b6040516100ce919061262d565b60405180910390f35b3480156100e357600080fd5b506001546100c1906001600160a01b031681565b34801561010357600080fd5b50610117610112366004612659565b6101f3565b6040519081526020016100ce565b34801561013157600080fd5b506101456101403660046126c9565b61022f565b005b6101456101553660046128f2565b6103b8565b34801561016657600080fd5b50610145610175366004612a8d565b61067a565b34801561018657600080fd5b50610145610195366004612aaa565b6107ae565b6101456101a8366004612adf565b6108b4565b3480156101b957600080fd5b506101456101c8366004612b7d565b611434565b3480156101d957600080fd5b506000546100c1906201000090046001600160a01b031681565b600061020a6001600160a01b038816333088611577565b61021787876000196115e2565b61022486868686866116c0565b979650505050505050565b600054610100900460ff161580801561024f5750600054600160ff909116105b806102695750303b158015610269575060005460ff166001145b6102d15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156102f4576000805461ff0019166101001790555b6001600160a01b03841661031b5760405163d92e233d60e01b815260040160405180910390fd5b600080546001600160a01b03808716620100000262010000600160b01b031990921691909117909155600180548583166001600160a01b031991821617909155600280549285169290911691909117905580156103b2576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b855160005b81811015610513578781815181106103d7576103d7612c02565b60200260200101516040015115610506578781815181106103fa576103fa612c02565b6020026020010151600001516001600160a01b031663f51cc7dd89838151811061042657610426612c02565b6020026020010151602001513060018c868151811061044757610447612c02565b6020026020010151606001518d878151811061046557610465612c02565b6020026020010151608001518e888151811061048357610483612c02565b602002602001015160a001518f89815181106104a1576104a1612c02565b602002602001015160c001516040518863ffffffff1660e01b81526004016104cf9796959493929190612c18565b600060405180830381600087803b1580156104e957600080fd5b505af11580156104fd573d6000803e3d6000fd5b5050505061050b565b610513565b6001016103bd565b5061052186868686866108b4565b60005b818110156106705787818151811061053e5761053e612c02565b6020026020010151604001516106685787818151811061056057610560612c02565b6020026020010151600001516001600160a01b031663f51cc7dd89838151811061058c5761058c612c02565b6020026020010151602001513060008c86815181106105ad576105ad612c02565b6020026020010151606001518d87815181106105cb576105cb612c02565b6020026020010151608001518e88815181106105e9576105e9612c02565b602002602001015160a001518f898151811061060757610607612c02565b602002602001015160c001516040518863ffffffff1660e01b81526004016106359796959493929190612c18565b600060405180830381600087803b15801561064f57600080fd5b505af1158015610663573d6000803e3d6000fd5b505050505b600101610524565b5050505050505050565b600054604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906106af90339060040161262d565b602060405180830381865afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f09190612c59565b15806107665750604051631c86b03760e31b81526001600160a01b0382169063e43581b89061072390339060040161262d565b602060405180830381865afa158015610740573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107649190612c59565b155b1561078457604051633b8d9d7560e21b815260040160405180910390fd5b600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b60005460405163521d4de960e01b8152620100009091046001600160a01b03169063521d4de9906107e390339060040161262d565b602060405180830381865afa158015610800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108249190612c59565b61084157604051632678482f60e21b815260040160405180910390fd5b6001600160a01b0382166108685760405163d92e233d60e01b815260040160405180910390fd5b8060ff1660000361089457600180546001600160a01b0384166001600160a01b03199091161790555050565b600280546001600160a01b0319166001600160a01b0384161790555b5050565b845160005b81811015610a34578681815181106108d3576108d3612c02565b6020026020010151600001516001600160a01b031663d505accf8883815181106108ff576108ff612c02565b602002602001015160200151308a858151811061091e5761091e612c02565b6020026020010151604001518b868151811061093c5761093c612c02565b6020026020010151606001518c878151811061095a5761095a612c02565b6020026020010151608001518d888151811061097857610978612c02565b602002602001015160a001518e898151811061099657610996612c02565b602090810291909101015160c001516040516001600160e01b031960e08a901b1681526001600160a01b0397881660048201529690951660248701526044860193909352606485019190915260ff16608484015260a483015260c482015260e401600060405180830381600087803b158015610a1157600080fd5b505af1158015610a25573d6000803e3d6000fd5b505050508060010190506108b9565b508360005b81811015610670576000878783818110610a5557610a55612c02565b9050602002016020810190610a6a9190612c8c565b601b811115610a7b57610a7b612c76565b03610b52576000806000878785818110610a9757610a97612c02565b9050602002810190610aa99190612cad565b810190610ab69190612cfe565b9250925092506000198103610b35576040516370a0823160e01b81526001600160a01b038416906370a0823190610af190339060040161262d565b602060405180830381865afa158015610b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b329190612d3f565b90505b610b4a6001600160a01b038416338484611577565b50505061142c565b6001878783818110610b6657610b66612c02565b9050602002016020810190610b7b9190612c8c565b601b811115610b8c57610b8c612c76565b03610b9f57610b9961172e565b5061142c565b6002878783818110610bb357610bb3612c02565b9050602002016020810190610bc89190612c8c565b601b811115610bd957610bd9612c76565b03610c2057600080868684818110610bf357610bf3612c02565b9050602002810190610c059190612cad565b810190610c129190612d58565b91509150610b4a828261179e565b6003878783818110610c3457610c34612c02565b9050602002016020810190610c499190612c8c565b601b811115610c5a57610c5a612c76565b03610ca6576000806000878785818110610c7657610c76612c02565b9050602002810190610c889190612cad565b810190610c959190612d88565b925092509250610b4a8383836118a0565b6004878783818110610cba57610cba612c02565b9050602002016020810190610ccf9190612c8c565b601b811115610ce057610ce0612c76565b03610cf657478015610b9957610b993382611936565b6006878783818110610d0a57610d0a612c02565b9050602002016020810190610d1f9190612c8c565b601b811115610d3057610d30612c76565b03610d85576000806000878785818110610d4c57610d4c612c02565b9050602002810190610d5e9190612cad565b810190610d6b9190612e2e565b925092509250610d7c838383611962565b5050505061142c565b6007878783818110610d9957610d99612c02565b9050602002016020810190610dae9190612c8c565b601b811115610dbf57610dbf612c76565b03610e0d57600080868684818110610dd957610dd9612c02565b9050602002810190610deb9190612cad565b810190610df89190612e86565b91509150610e068282611a18565b505061142c565b6009878783818110610e2157610e21612c02565b9050602002016020810190610e369190612c8c565b601b811115610e4757610e47612c76565b03610ecc5760008060008060008060008b8b89818110610e6957610e69612c02565b9050602002810190610e7b9190612cad565b810190610e889190613026565b9650965096509650965096509650610ea28383888a611aa7565b9150610eb187876000196115e2565b610ebf868484888886611f56565b505050505050505061142c565b600a878783818110610ee057610ee0612c02565b9050602002016020810190610ef59190612c8c565b601b811115610f0657610f06612c76565b03610f705760008060008060008060008b8b89818110610f2857610f28612c02565b9050602002810190610f3a9190612cad565b810190610f4791906130fc565b9650965096509650965096509650610f6487878787878787611ffa565b5050505050505061142c565b600b878783818110610f8457610f84612c02565b9050602002016020810190610f999190612c8c565b601b811115610faa57610faa612c76565b03611016576000806000806000898987818110610fc957610fc9612c02565b9050602002810190610fdb9190612cad565b810190610fe8919061317b565b94509450945094509450610fff85856000196115e2565b61100b8484848461206b565b50505050505061142c565b600c87878381811061102a5761102a612c02565b905060200201602081019061103f9190612c8c565b601b81111561105057611050612c76565b0361112a57600080600080600089898781811061106f5761106f612c02565b90506020028101906110819190612cad565b81019061108e919061317b565b945094509450945094506000198303611111576040516370a0823160e01b81526001600160a01b038616906370a08231906110cd90309060040161262d565b602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110e9190612d3f565b92505b61111e85856000196115e2565b61100b848484846120f1565b601b87878381811061113e5761113e612c02565b90506020020160208101906111539190612c8c565b601b81111561116457611164612c76565b03611242576000806000806000808a8a8881811061118457611184612c02565b90506020028101906111969190612cad565b8101906111a39190612659565b9550955095509550955095506000198403611228576040516370a0823160e01b81526001600160a01b038716906370a08231906111e490309060040161262d565b602060405180830381865afa158015611201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112259190612d3f565b93505b61123586866000196115e2565b610f6485858585856116c0565b600d87878381811061125657611256612c02565b905060200201602081019061126b9190612c8c565b601b81111561127c5761127c612c76565b0361134f5760008060008088888681811061129957611299612c02565b90506020028101906112ab9190612cad565b8101906112b891906131d6565b93509350935093506000198303611339576040516370a0823160e01b81526001600160a01b038516906370a08231906112f590339060040161262d565b602060405180830381865afa158015611312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113369190612d3f565b92505b61134584848484612175565b505050505061142c565b600e87878381811061136357611363612c02565b90506020020160208101906113789190612c8c565b601b81111561138957611389612c76565b036113d9576000806000808888868181106113a6576113a6612c02565b90506020028101906113b89190612cad565b8101906113c591906131d6565b9350935093509350611345848484846121aa565b61142c8787838181106113ee576113ee612c02565b90506020020160208101906114039190612c8c565b86868481811061141557611415612c02565b90506020028101906114279190612cad565b505050565b600101610a39565b60005460405163521d4de960e01b8152620100009091046001600160a01b03169063521d4de99061146990339060040161262d565b602060405180830381865afa158015611486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114aa9190612c59565b6114c757604051632678482f60e21b815260040160405180910390fd5b8483811415806114d75750808214155b156114f5576040516346282e8d60e01b815260040160405180910390fd5b60005b818110156106705761156f88888381811061151557611515612c02565b905060200201602081019061152a9190612a8d565b87878481811061153c5761153c612c02565b90506020020160208101906115519190612a8d565b86868581811061156357611563612c02565b905060200201356115e2565b6001016114f8565b6040516001600160a01b03808516602483015283166044820152606481018290526103b29085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526121e0565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e90611613903090879060040161321e565b602060405180830381865afa158015611630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116549190612d3f565b90508181108015611670575061166d600260001961324e565b81105b1561169957611694836116838385613270565b6001600160a01b03871691906122b2565b6103b2565b818111156103b2576103b2836116af8484613270565b6001600160a01b038716919061234f565b60006116ce868686866120f1565b60408051338152602081018890529081018290529091506001600160a01b0380841691888216918716907ff0abe475665c1088274490f21db8d3d3351d565d49d5222cc54656fba17f49119060600160405180910390a495945050505050565b600073e5d7c2a44ffddf6b295a15c148167daaaf5cf34f6001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561177f57600080fd5b505af1158015611793573d6000803e3d6000fd5b505050505034905090565b6040516370a0823160e01b815260009073e5d7c2a44ffddf6b295a15c148167daaaf5cf34f906370a08231906117d890309060040161262d565b602060405180830381865afa1580156117f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118199190612d3f565b90506118258184612452565b801561189a57604051632e1a7d4d60e01b81526004810182905273e5d7c2a44ffddf6b295a15c148167daaaf5cf34f90632e1a7d4d90602401600060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b5050505061189a8282611936565b92915050565b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906118cf90309060040161262d565b602060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612d3f565b905061191c8184612452565b80156103b2576103b26001600160a01b0385168383612473565b600080600080600085875af1905080611427576040516312171d8360e31b815260040160405180910390fd5b6002546000906001600160a01b031661197e85826000196115e2565b600080826001600160a01b03168560405161199991906132a7565b6000604051808303816000865af19150503d80600081146119d6576040519150601f19603f3d011682016040523d82523d6000602084013e6119db565b606091505b5091509150816119ee576119ee81612492565b80806020019051810190611a029190612d3f565b9350611a0e8487612452565b5050509392505050565b805160005b818110156103b257828181518110611a3757611a37612c02565b60200260200101516001600160a01b03166384e9bd7e856040518263ffffffff1660e01b8152600401611a6a919061262d565b600060405180830381600087803b158015611a8457600080fd5b505af1158015611a98573d6000803e3d6000fd5b50505050806001019050611a1d565b83516060906000816001600160401b03811115611ac657611ac6612714565b604051908082528060200260200182016040528015611aef578160200160208202803683370190505b5090506000806000805b85811015611f44576000808c8381518110611b1657611b16612c02565b60200260200101516007811115611b2f57611b2f612c76565b03611b3e576001945050611f3c565b60028c8381518110611b5257611b52612c02565b60200260200101516007811115611b6b57611b6b612c76565b03611c615760008b8381518110611b8457611b84612c02565b6020026020010151806020019051810190611b9f91906132c3565b909250905060018101611c5a576040516370a0823160e01b815282906001600160a01b038c16906370a0823190611bda90309060040161262d565b602060405180830381865afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1b9190612d3f565b6040805160208101939093528201526060016040516020818303038152906040528c8481518110611c4e57611c4e612c02565b60200260200101819052505b5050611f3c565b60038c8381518110611c7557611c75612c02565b60200260200101516007811115611c8e57611c8e612c76565b1480611cc4575060058c8381518110611ca957611ca9612c02565b60200260200101516007811115611cc257611cc2612c76565b145b15611cfe578a8281518110611cdb57611cdb612c02565b6020026020010151806020019051810190611cf691906132c3565b509050611dd5565b60018c8381518110611d1257611d12612c02565b60200260200101516007811115611d2b57611d2b612c76565b03611d64578a8281518110611d4257611d42612c02565b6020026020010151806020019051810190611d5d9190612d3f565b9050611dd5565b60068c8381518110611d7857611d78612c02565b60200260200101516007811115611d9157611d91612c76565b03611dcf578a8281518110611da857611da8612c02565b6020026020010151806020019051810190611dc391906132e7565b50919250611dd5915050565b50611f3c565b80600003611e59578415611de95750611f3c565b83600003611e5657896001600160a01b0316633c2e941b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e539190612d3f565b93505b50825b60005b83811015611e825781878281518110611e7757611e77612c02565b505050600101611e5c565b5060405163430c208160e01b81526001600160a01b038b169063430c208190611eb19033908590600401613326565b602060405180830381865afa158015611ece573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef29190612c59565b611f0f5760405163390cdd9b60e21b815260040160405180910390fd5b80868481518110611f2257611f22612c02565b6020908102919091010152611f3860018461333f565b9250505b600101611af9565b5088955050505050505b949350505050565b611f816040518060800160405280600081526020016000815260200160008152602001600081525090565b604051631bd1f8d360e31b81526001600160a01b0388169063de8fc69890611fb7908990899033908a908a908a906004016133da565b6080604051808303816000875af1158015611fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610224919061349b565b60405163a5d4096b60e01b81526001600160a01b0388169063a5d4096b9061203090899089908990899089908990600401613504565b600060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b5050505050505050505050565b6040516394bf804d60e01b8152600481018490526001600160a01b038381166024830152600091611f4e918491908816906394bf804d906044015b6020604051808303816000875af11580156120c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e99190612d3f565b925082612452565b604051636e553f6560e01b8152600481018490526001600160a01b038381166024830152600091611f4e91871690636e553f65906044015b6020604051808303816000875af1158015612148573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216c9190612d3f565b91508183612452565b6000611f4e856001600160a01b031663ba0876528686336040518463ffffffff1660e01b815260040161212993929190613552565b6000611f4e82866001600160a01b031663b460af948787336040518463ffffffff1660e01b81526004016120a693929190613552565b6000612235826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124ba9092919063ffffffff16565b80519091501561142757808060200190518101906122539190612c59565b6114275760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102c8565b600081846001600160a01b031663dd62ed3e30866040518363ffffffff1660e01b81526004016122e392919061321e565b602060405180830381865afa158015612300573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123249190612d3f565b61232e919061333f565b90506103b28463095ea7b360e01b85846040516024016115ab929190613326565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e90612380903090879060040161321e565b602060405180830381865afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c19190612d3f565b9050818110156124255760405162461bcd60e51b815260206004820152602960248201527f5361666545524332303a2064656372656173656420616c6c6f77616e63652062604482015268656c6f77207a65726f60b81b60648201526084016102c8565b6040518282039061244b90869063095ea7b360e01b906115ab9088908690602401613326565b5050505050565b808210156108b05760405163a1aabbe160e01b815260040160405180910390fd5b6114278363a9059cbb60e01b84846040516024016115ab929190613326565b8051156124a157805181602001fd5b60405163ee418e3760e01b815260040160405180910390fd5b60606124c984846000856124d3565b90505b9392505050565b6060824710156125345760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102c8565b6001600160a01b0385163b61258b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102c8565b600080866001600160a01b031685876040516125a791906132a7565b60006040518083038185875af1925050503d80600081146125e4576040519150601f19603f3d011682016040523d82523d6000602084013e6125e9565b606091505b5091509150610224828286606083156126035750816124cc565b8251156126135782518084602001fd5b8160405162461bcd60e51b81526004016102c89190613571565b6001600160a01b0391909116815260200190565b6001600160a01b038116811461265657600080fd5b50565b60008060008060008060c0878903121561267257600080fd5b863561267d81612641565b9550602087013561268d81612641565b94506040870135935060608701356126a481612641565b92506080870135915060a08701356126bb81612641565b809150509295509295509295565b6000806000606084860312156126de57600080fd5b83356126e981612641565b925060208401356126f981612641565b9150604084013561270981612641565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171561274c5761274c612714565b60405290565b604051601f8201601f191681016001600160401b038111828210171561277a5761277a612714565b604052919050565b60006001600160401b0382111561279b5761279b612714565b5060051b60200190565b801515811461265657600080fd5b803560ff811681146127c457600080fd5b919050565b600082601f8301126127da57600080fd5b81356127ed6127e882612782565b612752565b80828252602082019150602060e0840286010192508583111561280f57600080fd5b602085015b8381101561289d5760e0818803121561282c57600080fd5b61283461272a565b813561283f81612641565b8152602082013561284f81612641565b60208201526040828101359082015260608083013590820152612874608083016127b3565b608082015260a0828101359082015260c08083013590820152835260209092019160e001612814565b5095945050505050565b60008083601f8401126128b957600080fd5b5081356001600160401b038111156128d057600080fd5b6020830191508360208260051b85010111156128eb57600080fd5b9250929050565b6000806000806000806080878903121561290b57600080fd5b86356001600160401b0381111561292157600080fd5b8701601f8101891361293257600080fd5b80356129406127e882612782565b80828252602082019150602060e0840285010192508b83111561296257600080fd5b6020840193505b828410156129fe5760e0848d03121561298157600080fd5b61298961272a565b843561299481612641565b815260208501356129a481612641565b602082015260408501356129b7816127a5565b6040820152606085810135908201526129d2608086016127b3565b608082015260a0858101359082015260c08086013590820152825260e090930192602090910190612969565b985050505060208701356001600160401b03811115612a1c57600080fd5b612a2889828a016127c9565b95505060408701356001600160401b03811115612a4457600080fd5b612a5089828a016128a7565b90955093505060608701356001600160401b03811115612a6f57600080fd5b612a7b89828a016128a7565b979a9699509497509295939492505050565b600060208284031215612a9f57600080fd5b81356124cc81612641565b60008060408385031215612abd57600080fd5b8235612ac881612641565b9150612ad6602084016127b3565b90509250929050565b600080600080600060608688031215612af757600080fd5b85356001600160401b03811115612b0d57600080fd5b612b19888289016127c9565b95505060208601356001600160401b03811115612b3557600080fd5b612b41888289016128a7565b90955093505060408601356001600160401b03811115612b6057600080fd5b612b6c888289016128a7565b969995985093965092949392505050565b60008060008060008060608789031215612b9657600080fd5b86356001600160401b03811115612bac57600080fd5b612bb889828a016128a7565b90975095505060208701356001600160401b03811115612bd757600080fd5b612be389828a016128a7565b90955093505060408701356001600160401b03811115612a6f57600080fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0397881681529590961660208601529215156040850152606084019190915260ff16608083015260a082015260c081019190915260e00190565b600060208284031215612c6b57600080fd5b81516124cc816127a5565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612c9e57600080fd5b8135601c81106124cc57600080fd5b6000808335601e19843603018112612cc457600080fd5b8301803591506001600160401b03821115612cde57600080fd5b6020019150368190038213156128eb57600080fd5b80356127c481612641565b600080600060608486031215612d1357600080fd5b8335612d1e81612641565b92506020840135612d2e81612641565b929592945050506040919091013590565b600060208284031215612d5157600080fd5b5051919050565b60008060408385031215612d6b57600080fd5b823591506020830135612d7d81612641565b809150509250929050565b600080600060608486031215612d9d57600080fd5b8335612da881612641565b925060208401359150604084013561270981612641565b600082601f830112612dd057600080fd5b81356001600160401b03811115612de957612de9612714565b612dfc601f8201601f1916602001612752565b818152846020838601011115612e1157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215612e4357600080fd5b8335612e4e81612641565b92506020840135915060408401356001600160401b03811115612e7057600080fd5b612e7c86828701612dbf565b9150509250925092565b60008060408385031215612e9957600080fd5b8235612ea481612641565b915060208301356001600160401b03811115612ebf57600080fd5b8301601f81018513612ed057600080fd5b8035612ede6127e882612782565b8082825260208201915060208360051b850101925087831115612f0057600080fd5b6020840193505b82841015612f2b578335612f1a81612641565b825260209384019390910190612f07565b809450505050509250929050565b600082601f830112612f4a57600080fd5b8135612f586127e882612782565b8082825260208201915060208360051b860101925085831115612f7a57600080fd5b602085015b8381101561289d57803560088110612f9657600080fd5b835260209283019201612f7f565b600082601f830112612fb557600080fd5b8135612fc36127e882612782565b8082825260208201915060208360051b860101925085831115612fe557600080fd5b602085015b8381101561289d5780356001600160401b0381111561300857600080fd5b613017886020838a0101612dbf565b84525060209283019201612fea565b600080600080600080600060e0888a03121561304157600080fd5b873561304c81612641565b965061305a60208901612cf3565b955061306860408901612cf3565b945061307660608901612cf3565b935060808801356001600160401b0381111561309157600080fd5b61309d8a828b01612f39565b93505060a08801356001600160401b038111156130b957600080fd5b6130c58a828b01612fa4565b92505060c08801356001600160401b038111156130e157600080fd5b6130ed8a828b01612dbf565b91505092959891949750929550565b600080600080600080600060e0888a03121561311757600080fd5b873561312281612641565b9650602088013561313281612641565b9550604088013561314281612641565b9450606088013561315281612641565b93506080880135925060a0880135915060c08801356001600160401b038111156130e157600080fd5b600080600080600060a0868803121561319357600080fd5b853561319e81612641565b945060208601356131ae81612641565b93506040860135925060608601356131c581612641565b949793965091946080013592915050565b600080600080608085870312156131ec57600080fd5b84356131f781612641565b935060208501359250604085013561320e81612641565b9396929550929360600135925050565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b60008261326b57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561189a5761189a613238565b60005b8381101561329e578181015183820152602001613286565b50506000910152565b600082516132b9818460208701613283565b9190910192915050565b600080604083850312156132d657600080fd5b505080516020909101519092909150565b600080600080608085870312156132fd57600080fd5b8451602086015190945061331081612641565b6040860151606090960151949790965092505050565b6001600160a01b03929092168252602082015260400190565b8082018082111561189a5761189a613238565b6000815180845261336a816020860160208601613283565b601f01601f19169290920160200192915050565b600082825180855260208501945060208160051b8301016020850160005b838110156133ce57601f198584030188526133b8838351613352565b602098890198909350919091019060010161339c565b50909695505050505050565b60c08082528751908201819052600090602089019060e0840190835b818110156134325783516008811061341e57634e487b7160e01b600052602160045260246000fd5b8352602093840193909201916001016133f6565b50508381036020850152613446818a61337e565b91505061345e60408401886001600160a01b03169052565b6001600160a01b03861660608401526001600160a01b038516608084015282810360a084015261348e8185613352565b9998505050505050505050565b600060808284031280156134ae57600080fd5b50604051600090608081016001600160401b03811182821017156134d4576134d4612714565b60409081528451825260208086015190830152848101519082015260609384015193810193909352509092915050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c060a0820181905260009061354690830184613352565b98975050505050505050565b9283526001600160a01b03918216602084015216604082015260600190565b6020815260006124cc602083018461335256fea2646970667358221220af02a6830f3506091b8a99377aa49884c4255b6d2022f57bd3aa200ff85065be64736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.