Source Code
Overview
GLMR Balance
GLMR Value
$0.00View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Aggregator
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 500 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.9;
import "./base/AggregatorBase.sol";
import "./helpers/TransferHelper.sol";
import "./interfaces/IAlgebraSwapRouter.sol";
import "./helpers/Path.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Aggregator is AggregatorBase {
using Path for bytes;
function initialize(RouterParameters memory params) public initializer {
AggregatorBase.initializerr(params);
}
function execute(
Command[] calldata commands,
bytes[] calldata inputs // with abi.encode it gives InvalidSignatureLength(), so we pass here
) public payable {
require(commands.length < 10, "Too many commands for executor.");
require(
commands.length == inputs.length,
"Amount of commands must match inputs."
);
for (uint256 i = 0; i < commands.length; ++i) {
if (commands[i].instruction == InstructionType.V3_EXACT_IN) {
(
bytes memory path,
address recipient,
uint256 deadline,
uint256 amountIn,
uint256 amountOutMinimum
) = abi.decode(
inputs[i],
(bytes, address, uint256, uint256, uint256)
);
require(recipient != address(0), "Zero Address");
//fetch the first token
(address tokenA,) = path.decodeFirstPool();
IStellaSwapV2ERC20(tokenA).approve(address(v3Router),amountIn);
IAlgebraSwapRouter(v3Router).exactInput(
IAlgebraSwapRouter.ExactInputParams({
path: path,
recipient: recipient,
deadline: deadline,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum
})
);
}
if (commands[i].instruction == InstructionType.V3_EXACT_OUT) {
(
bytes memory path,
address recipient,
uint256 deadline,
uint256 amountOut,
uint256 amountInMaximum
) = abi.decode(
inputs[i],
(bytes, address, uint256, uint256, uint256)
);
require(recipient != address(0), "Zero Address");
//approve last token in the reversed path in v3_exact_out
address lastToken = path.getLastPoolToken();
IStellaSwapV2ERC20(lastToken).approve(address(v3Router), amountInMaximum);
//need to encode path
IAlgebraSwapRouter(v3Router).exactOutput(
IAlgebraSwapRouter.ExactOutputParams({
path: path,
recipient: recipient,
deadline: deadline,
amountOut: amountOut,
amountInMaximum: amountInMaximum
})
);
}
if (commands[i].instruction == InstructionType.V2_EXACT_IN) {
(
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
address to,
uint256 deadline
) = abi.decode(
inputs[i],
(uint256, uint256, address[], address, uint256)
);
require(to != address(0), "Zero Address");
IStellaSwapV2ERC20(path[0]).approve(address(v2router), amountIn);
v2router.swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline);
}
if (commands[i].instruction == InstructionType.V2_EXACT_OUT) {
(
uint256 amountOut,
uint256 amountInMax,
address[] memory path,
address to,
uint256 deadline
) = abi.decode(
inputs[i],
(uint256, uint256, address[], address, uint256)
);
require(to != address(0), "Zero Address");
IStellaSwapV2ERC20(path[0]).approve(address(v2router), amountInMax);
v2router.swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline);
}
if (commands[i].instruction == InstructionType.STABLE_SIMPLE) {
(
address basepool,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) = abi.decode(
inputs[i],
(address, uint8, uint8, uint256, uint256, uint256)
);
_stableApproval(basepool, tokenIndexFrom, dx);
IStableSwap(basepool).swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);
}
if (commands[i].instruction == InstructionType.STABLE_FROM_BASE) {
(
address pool,
address basePool,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) = abi.decode(
inputs[i],
(
address,
address,
uint8,
uint8,
uint256,
uint256,
uint256
)
);
_stableApproval(basePool, tokenIndexFrom, dx);
stableRouter.swapFromBase(IStableSwap(pool), IStableSwap(basePool), tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);
}
if (commands[i].instruction == InstructionType.STABLE_TO_BASE) {
(
address pool,
address basePool,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) = abi.decode(
inputs[i],
(
address,
address,
uint8,
uint8,
uint256,
uint256,
uint256
)
);
address poolToken = IStableSwap(pool).getToken(tokenIndexFrom);
IStellaSwapV2ERC20(poolToken).approve(address(stableRouter), dx);
stableRouter.swapToBase(IStableSwap(pool), IStableSwap(basePool), tokenIndexFrom, tokenIndexTo, dx, minDy, deadline);
}
if (commands[i].instruction == InstructionType.PERMIT2_TRANSFER) {
(
uint256 _amount,
address _owner,
address _user,
address _token,
uint256 _nonce,
uint256 _deadline,
bytes memory _signature
) = abi.decode(
inputs[i],
(
uint256,
address,
address,
address,
uint256,
uint256,
bytes
)
);
address permit2addr = address(permit2);
ISignatureTransfer.TokenPermissions
memory permitted = ISignatureTransfer.TokenPermissions({
amount: _amount,
token: _token
});
ISignatureTransfer(permit2addr).permitWitnessTransferFrom(
ISignatureTransfer.PermitTransferFrom({
permitted: permitted,
nonce: _nonce,
deadline: _deadline
}),
ISignatureTransfer.SignatureTransferDetails({
to: address(this),
requestedAmount: _amount
}),
msg.sender,
// witness
keccak256(abi.encode(WITNESS_TYPEHASH, Witness(_user))),
// witnessTypeString,
WITNESS_TYPE_STRING,
_signature
);
}
if (commands[i].instruction == InstructionType.WRAP_ETH) {
uint256 amount = abi.decode(inputs[i], (uint256));
require(
address(this).balance >= amount,
"Insufficient ETH balance"
);
weth.deposit{value: amount}();
}
if (commands[i].instruction == InstructionType.UNWRAP_ETH) {
//wglmr.withdraw (with users permit signature)
uint256 amount = abi.decode(inputs[i], (uint256));
weth.withdraw(amount);
}
if (commands[i].instruction == InstructionType.TRANSFER) {
(
address token,
address recipient,
uint256 value,
bool isEth
) = abi.decode(inputs[i], (address, address, uint256, bool));
require(recipient != address(0), "Zero Address");
if (isEth) {
TransferHelper.safeTransferETH(recipient, value);
} else {
TransferHelper.safeTransfer(token, recipient, value);
}
}
if (commands[i].instruction == InstructionType.SWEEP) {
(
address token,
address recipient,
bool isEth
) = abi.decode(inputs[i], (address, address, bool));
require(recipient != address(0), "Zero Address");
if (isEth) {
uint256 balance = address(this).balance;
TransferHelper.safeTransferETH(recipient, balance);
} else {
uint256 balance = IStellaSwapV2ERC20(token).balanceOf(address(this));
TransferHelper.safeTransfer(token, recipient, balance);
}
}
}
}
function _stableApproval(address pool, uint8 tokenIndex, uint256 amount) internal {
address poolToken = IStableSwap(pool).getToken(tokenIndex);
IStellaSwapV2ERC20(poolToken).approve(address(pool), amount);
IStellaSwapV2ERC20(poolToken).approve(address(stableRouter), amount);
}
receive() external payable {}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import './IAlgebraSwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Algebra
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-periphery
interface IAlgebraSwapRouter is IAlgebraSwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 limitSqrtPrice;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 limitSqrtPrice;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @dev Unlike standard swaps, handles transferring from user before the actual swap.
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingleSupportingFeeOnTransferTokens(ExactInputSingleParams calldata params)
external
returns (uint256 amountOut);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import './BytesLib.sol';
/// @title Functions for manipulating path data for multihop swaps
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-periphery
library Path {
using BytesLib for bytes;
/// @dev The length of the bytes encoded address
uint256 private constant ADDR_SIZE = 20;
/// @dev The length of the bytes encoded fee
uint256 private constant FEE_SIZE = 3;
/// @dev The offset of a single token address and pool fee
uint256 private constant NEXT_OFFSET = ADDR_SIZE;
/// @dev The offset of an encoded pool key
uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
/// @dev The minimum length of an encoding that contains 2 or more pools
uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;
/// @notice Returns true iff the path contains two or more pools
/// @param path The encoded swap path
/// @return True if path contains two or more pools, otherwise false
function hasMultiplePools(bytes memory path) internal pure returns (bool) {
return path.length >= MULTIPLE_POOLS_MIN_LENGTH;
}
/// @notice Returns the number of pools in the path
/// @param path The encoded swap path
/// @return The number of pools in the path
function numPools(bytes memory path) internal pure returns (uint256) {
// Ignore the first token address. From then on every fee and token offset indicates a pool.
return ((path.length - ADDR_SIZE) / NEXT_OFFSET);
}
/// @notice Decodes the first pool in path
/// @param path The bytes encoded swap path
/// @return tokenA The first token of the given pool
/// @return tokenB The second token of the given pool
function decodeFirstPool(bytes memory path) internal pure returns (address tokenA, address tokenB) {
tokenA = path.toAddress(0);
tokenB = path.toAddress(NEXT_OFFSET);
}
/// @notice Gets the segment corresponding to the first pool in the path
/// @param path The bytes encoded swap path
/// @return The segment containing all data necessary to target the first pool in the path
function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
return path.slice(0, POP_OFFSET);
}
function getLastPoolToken(bytes memory path) internal pure returns (address lastPool) {
lastPool = path.toAddress(path.length - 20);
}
/// @notice Skips a token + fee element from the buffer and returns the remainder
/// @param path The swap path
/// @return The remaining token + fee elements in the path
function skipToken(bytes memory path) internal pure returns (bytes memory) {
return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}pragma solidity ^0.8.17;
import "../interfaces/IWETH.sol";
import "../interfaces/IAlgebraSwapRouter.sol";
import "../interfaces/IStellaSwapV2Router02.sol";
import "../interfaces/ISignatureTransfer.sol";
import "../interfaces/IStableSwapRouter.sol";
import "../interfaces/IStellaSwapV2ERC20.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
struct RouterParameters {
IAlgebraSwapRouter v3router;
IStellaSwapV2Router02 v2router;
IStableSwapRouter stableRouter;
ISignatureTransfer permit2;
IWETH weth;
}
contract AggregatorBase is Initializable {
//Aggregator is a contract that takes commands, data, and a signature from the user
//to transfer their tokens to operate on them.
ISignatureTransfer public permit2;
IAlgebraSwapRouter public v3Router;
IStellaSwapV2Router02 public v2router;
IStableSwapRouter public stableRouter;
IWETH public weth;
string public constant WITNESS_TYPE_STRING =
"Witness witness)TokenPermissions(address token,uint256 amount)Witness(address user)";
bytes32 public constant WITNESS_TYPEHASH =
keccak256("Witness(address user)");
enum AMM {
V2,
V3,
STABLE
}
//will the tokens stay in the router for the next command to use or go to user?
enum Destination {
ROUTER,
MSG_SENDER
}
//v2 v3 stable etc all use the same commands for simplifying the API
enum InstructionType {
V3_EXACT_IN,
V3_EXACT_OUT,
V2_EXACT_IN,
V2_EXACT_OUT,
PERMIT2_TRANSFER, //giving tokens for aggregator to trade with
WRAP_ETH, //turn users GLMR to WGLMR
UNWRAP_ETH, //reverse
SWEEP, //say user had negative slippage, send the remaining funds back
TRANSFER, // simple transfer helper
STABLE_SIMPLE, // simple transfer helper
STABLE_TO_BASE,// simple transfer helper
STABLE_FROM_BASE // simple transfer helper
}
struct SwapArguments {
uint256 inputAmount;
uint256 outputAmount;
uint256 desiredInput;
uint256 desiredOutput;
}
struct Command {
InstructionType instruction;
}
struct Witness {
// Address of the user that signer is giving the tokens to
address user;
}
function initializerr(RouterParameters memory params) public onlyInitializing {
permit2 = params.permit2;
v3Router = params.v3router;
v2router = params.v2router;
stableRouter = params.stableRouter;
weth = params.weth;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (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.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
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.
*
* 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.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* 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.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
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.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IAlgebraPoolActions#swap
/// @notice Any contract that calls IAlgebraPoolActions#swap must implement this interface
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraSwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call
function algebraSwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer {
/// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
/// @param maxAmount The maximum amount a spender can request to transfer
error InvalidAmount(uint256 maxAmount);
/// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
/// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
error LengthMismatch();
/// @notice Emits an event when the owner successfully invalidates an unordered nonce.
event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);
/// @notice The token and amount details for a transfer signed in the permit transfer signature
struct TokenPermissions {
// ERC20 token address
address token;
// the maximum amount that can be spent
uint256 amount;
}
/// @notice The signed permit message for a single token transfer
struct PermitTransferFrom {
TokenPermissions permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
/// @notice Specifies the recipient address and amount for batched transfers.
/// @dev Recipients and amounts correspond to the index of the signed token permissions array.
/// @dev Reverts if the requested amount is greater than the permitted signed amount.
struct SignatureTransferDetails {
// recipient address
address to;
// spender requested amount
uint256 requestedAmount;
}
/// @notice Used to reconstruct the signed permit message for multiple token transfers
/// @dev Do not need to pass in spender address as it is required that it is msg.sender
/// @dev Note that a user still signs over a spender address
struct PermitBatchTransferFrom {
// the tokens and corresponding amounts permitted for a transfer
TokenPermissions[] permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
/// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
/// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
/// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
/// @dev It returns a uint256 bitmap
/// @dev The index, or wordPosition is capped at type(uint248).max
function nonceBitmap(address, uint256) external view returns (uint256);
/// @notice Transfers a token using a signed permit message
/// @dev Reverts if the requested amount is greater than the permitted signed amount
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails The spender's requested transfer details for the permitted token
/// @param signature The signature to verify
function permitTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes calldata signature
) external;
/// @notice Transfers a token using a signed permit message
/// @notice Includes extra data provided by the caller to verify signature over
/// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
/// @dev Reverts if the requested amount is greater than the permitted signed amount
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails The spender's requested transfer details for the permitted token
/// @param witness Extra data to include when checking the user signature
/// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
/// @param signature The signature to verify
function permitWitnessTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
/// @notice Transfers multiple tokens using a signed permit message
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails Specifies the recipient and requested amount for the token transfer
/// @param signature The signature to verify
function permitTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes calldata signature
) external;
/// @notice Transfers multiple tokens using a signed permit message
/// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
/// @notice Includes extra data provided by the caller to verify signature over
/// @param permit The permit data signed over by the owner
/// @param owner The owner of the tokens to transfer
/// @param transferDetails Specifies the recipient and requested amount for the token transfer
/// @param witness Extra data to include when checking the user signature
/// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
/// @param signature The signature to verify
function permitWitnessTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
/// @notice Invalidates the bits specified in mask for the bitmap at the word position
/// @dev The wordPos is maxed at type(uint248).max
/// @param wordPos A number to index the nonceBitmap at
/// @param mask A bitmap masked against msg.sender's current bitmap at the word position
function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
import "./IStableSwap.sol";
interface IStableSwapRouter {
function swapFromBase(
IStableSwap pool,
IStableSwap basePool,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) external returns (uint256);
function swapToBase(
IStableSwap pool,
IStableSwap basePool,
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) external returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
interface IStellaSwapV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2;
import './IStellaSwapV2Router01.sol';
interface IStellaSwapV2Router02 is IStellaSwapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
interface IStableSwap {
function swap(
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) external returns (uint256);
function getLpToken() external returns (address);
function getToken(uint8 index) external returns (address);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2;
interface IStellaSwapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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);
}
}
}{
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 500
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[],"name":"WITNESS_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITNESS_TYPE_STRING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum AggregatorBase.InstructionType","name":"instruction","type":"uint8"}],"internalType":"struct AggregatorBase.Command[]","name":"commands","type":"tuple[]"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IAlgebraSwapRouter","name":"v3router","type":"address"},{"internalType":"contract IStellaSwapV2Router02","name":"v2router","type":"address"},{"internalType":"contract IStableSwapRouter","name":"stableRouter","type":"address"},{"internalType":"contract ISignatureTransfer","name":"permit2","type":"address"},{"internalType":"contract IWETH","name":"weth","type":"address"}],"internalType":"struct RouterParameters","name":"params","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IAlgebraSwapRouter","name":"v3router","type":"address"},{"internalType":"contract IStellaSwapV2Router02","name":"v2router","type":"address"},{"internalType":"contract IStableSwapRouter","name":"stableRouter","type":"address"},{"internalType":"contract ISignatureTransfer","name":"permit2","type":"address"},{"internalType":"contract IWETH","name":"weth","type":"address"}],"internalType":"struct RouterParameters","name":"params","type":"tuple"}],"name":"initializerr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"contract ISignatureTransfer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stableRouter","outputs":[{"internalType":"contract IStableSwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"v2router","outputs":[{"internalType":"contract IStellaSwapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"v3Router","outputs":[{"internalType":"contract IAlgebraSwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60808060405234610016576120e4908161001c8239f35b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c80630dc91306146100e357806312261ee7146100da578063156e2152146100d15780632c03ae6a146100c85780633fc8cef3146100bf5780634c3677c8146100b65780638f656d22146100ad5780638f8dc10a146100a4578063d7f478ee1461009b5763ff08da6e0361000e57610096610775565b61000e565b506100966105f2565b506100966105ca565b50610096610482565b506100966103dc565b506100966103b4565b50610096610378565b50610096610343565b50610096610124565b506100966100fc565b60009103126100f757565b600080fd5b50346100f75760003660031901126100f75760206001600160a01b0360015416604051908152f35b50346100f75760003660031901126100f75760206001600160a01b0360005460101c16604051908152f35b50634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761018257604052565b61018a61014f565b604052565b67ffffffffffffffff811161018257604052565b90601f8019910116810190811067ffffffffffffffff82111761018257604052565b604051906101d282610166565b565b604051906040820182811067ffffffffffffffff82111761018257604052565b604051906060820182811067ffffffffffffffff82111761018257604052565b604051906020820182811067ffffffffffffffff82111761018257604052565b60209067ffffffffffffffff8111610252575b601f01601f19160190565b61025a61014f565b610247565b604051906080820182811067ffffffffffffffff8211176102f6575b604052605382527f746e6573732861646472657373207573657229000000000000000000000000006060837f5769746e657373207769746e65737329546f6b656e5065726d697373696f6e7360208201527f286164647265737320746f6b656e2c75696e7432353620616d6f756e7429576960408201520152565b6102fe61014f565b61027b565b919082519283825260005b84811061032f575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161030e565b50346100f75760003660031901126100f75761037461036061025f565b604051918291602083526020830190610303565b0390f35b50346100f75760003660031901126100f75760206040517ffeed45b61d43f452c933000e813412318e408c352e137cba26cfbe202b355c3a8152f35b50346100f75760003660031901126100f75760206001600160a01b0360045416604051908152f35b50346100f75760003660031901126100f75760206001600160a01b0360035416604051908152f35b6001600160a01b038116036100f757565b60a09060031901126100f75760405161042d81610166565b60043561043981610404565b815260243561044781610404565b602082015260443561045881610404565b604082015260643561046981610404565b606082015260843561047a81610404565b608082015290565b50346100f75761049136610415565b6000549060ff8260081c1615809281936105bc575b811561059c575b5015610531576104d390826104ca600160ff196000541617600055565b61051857611e10565b6104d957005b6104e961ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b61052c61010061ff00196000541617600055565b611e10565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b303b159150816105ae575b50386104ad565b6001915060ff1614386105a7565b600160ff82161091506104a6565b50346100f75760003660031901126100f75760206001600160a01b0360025416604051908152f35b50346100f75761060136610415565b6000549060ff8260081c16156106eb576080816100199362010000600160b01b0360606106cf95015160101b169062010000600160b01b031916176000556001600160a01b038151166001600160a01b0319600154161760015561068e61067260208301516001600160a01b031690565b6001600160a01b03166001600160a01b03196002541617600255565b6106c16106a560408301516001600160a01b031690565b6001600160a01b03166001600160a01b03196003541617600355565b01516001600160a01b031690565b6001600160a01b03166001600160a01b03196004541617600455565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b9181601f840112156100f75782359167ffffffffffffffff83116100f7576020808501948460051b0101116100f757565b5060403660031901126100f75767ffffffffffffffff6004358181116100f7576107a3903690600401610744565b916024359081116100f7576107bc903690600401610744565b906107c9600a8510611597565b6107d48285146115e3565b60005b8481106107e057005b6107f36107ee828787611687565b6116c5565b6107fc816116a5565b15611473575b6108106107ee828787611687565b610819816116a5565b600180911461131b575b506108326107ee828787611687565b61083b816116a5565b60028091146111e7575b60036108556107ee848989611687565b61085e816116a5565b1461109a575b5060096108756107ee838888611687565b61087e816116a5565b14610fda575b600b6108946107ee838888611687565b61089d816116a5565b14610eeb575b600a6108b36107ee838888611687565b6108bc816116a5565b14610cf6575b60046108d26107ee838888611687565b6108db816116a5565b14610b92575b60056108f16107ee838888611687565b6108fa816116a5565b14610b12575b60066109106107ee838888611687565b610919816116a5565b14610a71575b8060086109336107ee610966948989611687565b61093c816116a5565b14610a23575b60076109526107ee838989611687565b61095b816116a5565b1461096b575b611654565b6107d7565b6109816109798286866116d2565b810190611c87565b916001600160a01b0380911691169161099b8315156117bf565b156109ac5750610961904790612017565b6040516370a0823160e01b81523060048201526109619260209290918381602481855afa938415610a16575b6000946109e7575b5050611f4a565b610a07929450803d10610a0f575b6109ff81836101a3565b810190611829565b9138806109e0565b503d6109f5565b610a1e61181c565b6109d8565b610a39610a318286866116d2565b810190611c4d565b90916001600160a01b0380911691610a528315156117bf565b15610a675750610a629250612017565b610942565b610a629316611f4a565b610a87610a7f8285856116d2565b810190611bf2565b90610aa9610a9d6004546001600160a01b031690565b6001600160a01b031690565b91823b156100f757604051632e1a7d4d60e01b81526004810191909152610966926000908290602490829084905af18015610b05575b610aec575b50905061091f565b80610af9610aff9261018f565b806100ec565b38610ae4565b610b0d61181c565b610adf565b610b20610a7f8285856116d2565b610b2c81471015611c01565b610b41610a9d6004546001600160a01b031690565b803b156100f757600090600460405180948193630d0e30db60e41b83525af18015610b85575b610b72575b50610900565b80610af9610b7f9261018f565b38610b6c565b610b8d61181c565b610b67565b610c77610c85610bae610ba68487876116d2565b810190611afe565b9792909596919450610c31610bd2610a9d6000546001600160a01b039060101c1690565b91610bdb6101d4565b6001600160a01b03918216815297816020948b868c01521697610bfc6101f4565b998a52848a01526040890152610c106101d4565b30815298838a0152610c20610214565b951685906001600160a01b03169052565b6040519283918201948591909160206001600160a01b0360408301947ffeed45b61d43f452c933000e813412318e408c352e137cba26cfbe202b355c3a84525116910152565b03601f1981018352826101a3565b51902091610c9161025f565b94823b156100f757600094610cc08692604051988997889687956309be14ff60e11b8752339160048801611b63565b03925af18015610ce9575b610cd6575b506108e1565b80610af9610ce39261018f565b38610cd0565b610cf161181c565b610ccb565b610d018184846116d2565b8101610d0c91611a96565b60405162415c3360e91b815260ff861660048201529295939493869390916001600160a01b038916826024815a602094600091f1938415986001600160a01b0398610db360208b99600099610e3598839f610ede575b8b91610eb1575b50610d7f610a9d6003546001600160a01b031690565b8b8d60405180978196829563095ea7b360e01b845260048401602090939291936001600160a01b0360408201951681520152565b0393165af18015610ea4575b610e77575b50610dda610a9d6003546001600160a01b031690565b986040519c8d9b8c9a8b99637fcb499160e11b8b52169116600489019360ff60c0969399989794819360e088019b6001600160a01b038092168952166020880152166040860152166060840152608083015260a08201520152565b03925af18015610e6a575b610e4b575b506108c2565b610e639060203d602011610a0f576109ff81836101a3565b5038610e45565b610e7261181c565b610e40565b610e96908c3d8e11610e9d575b610e8e81836101a3565b810190611804565b5038610dc4565b503d610e84565b610eac61181c565b610dbf565b610ed19150833d8511610ed7575b610ec981836101a3565b810190611ae9565b38610d69565b503d610ebf565b610ee661181c565b610d62565b6000610f03610efb8386866116d2565b810190611a96565b610f986001600160a01b03989294959397969880991691610f25898685611cba565b610f3a610a9d6003546001600160a01b031690565b95604051998a98899788966338c7897360e01b885260209e8f9d16600489019360ff60c0969399989794819360e088019b6001600160a01b038092168952166020880152166040860152166060840152608083015260a08201520152565b03925af18015610fcd575b610faf575b50506108a3565b81610fc592903d10610a0f576109ff81836101a3565b503880610fa8565b610fd561181c565b610fa3565b60006110586001600160a01b03610ffd610ff58588886116d2565b810190611a51565b94979193959092971692611012818786611cba565b604051968795869485936348b4aac360e11b855260209b8c9a60048701919260ff60809497969592978160a0860199168552166020840152604083015260608201520152565b03925af1801561108d575b61106f575b5050610884565b8161108592903d10610a0f576109ff81836101a3565b503880611068565b61109561181c565b611063565b60006001600160a01b0361117c610a9d8361115e6110c46110bc898c8c6116d2565b8101906118a5565b9793949296919816996110d88b15156117bf565b866110f8610a9d610a9d6110eb8d611948565b516001600160a01b031690565b61110c610a9d84546001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b039190911660048201526024810192909252602091908290829060449082908c905af180156111da575b6111bc575b5050546001600160a01b031690565b9460405198899788968795634401edf760e11b8752600487016119d8565b03925af180156111af575b15610864576111a8903d806000833e6111a081836101a3565b81019061195e565b5038610864565b6111b761181c565b611187565b816111d292903d10610e9d57610e8e81836101a3565b50388061114f565b6111e261181c565b61114a565b6000806001600160a01b036112006110bc8689896116d2565b9396919416956112118715156117bf565b80611224610a9d610a9d6110eb89611948565b611238610a9d8b546001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b0391909116600482015260248101929092526020919082908290604490829088905af1801561130e575b6112f0575b50506112b2611294610a9d8a546001600160a01b031690565b94604051988997889687956338ed173960e01b8752600487016119d8565b03925af180156112e3575b6112c8575b50610845565b6112dc903d806000833e6111a081836101a3565b50386112c2565b6112eb61181c565b6112bd565b8161130692903d10610e9d57610e8e81836101a3565b50388061127b565b61131661181c565b611276565b6113268285856116d2565b810161133191611774565b91949390926001600160a01b03169061134b8215156117bf565b61135481611eec565b855460405163095ea7b360e01b81526001600160a01b03918216600482015260248101869052602098899791969391929091889188916044918391165a90600091f18015610a9d60009a611408996113dd946113c294611466575b611449575b50546001600160a01b031690565b956113cb6101c5565b9586526001600160a01b031688860152565b604084015260608301526080820152604051948580948193631e51809360e31b835260048301611838565b03925af1801561143c575b61141e575b50610823565b8161143492903d10610a0f576109ff81836101a3565b503880611418565b61144461181c565b611413565b61145f908c8d3d10610e9d57610e8e81836101a3565b50386113b4565b61146e61181c565b6113af565b61147e8184846116d2565b810161148991611774565b9092936001600160a01b03809516908115156114a4906117bf565b6114ad81611e81565b509260019586546114c4906001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b039190911660048201526024810182905260209889979196889188916044918391165a90600091f18015610a9d60009a6115559961152a946113c294611466576114495750546001600160a01b031690565b60408401526060830152608082015260405194858094819363c04b8d5960e01b835260048301611838565b03925af1801561158a575b61156c575b5050610802565b8161158292903d10610a0f576109ff81836101a3565b503880611565565b61159261181c565b611560565b1561159e57565b60405162461bcd60e51b815260206004820152601f60248201527f546f6f206d616e7920636f6d6d616e647320666f72206578656375746f722e006044820152606490fd5b156115ea57565b60405162461bcd60e51b815260206004820152602560248201527f416d6f756e74206f6620636f6d6d616e6473206d757374206d6174636820696e604482015264383aba399760d91b6064820152608490fd5b50634e487b7160e01b600052601160045260246000fd5b6001906000198114611664570190565b61166c61163d565b0190565b50634e487b7160e01b600052603260045260246000fd5b9190811015611698575b60051b0190565b6116a0611670565b611691565b600c11156116af57565b634e487b7160e01b600052602160045260246000fd5b35600c8110156100f75790565b9190811015611715575b60051b81013590601e19813603018212156100f757019081359167ffffffffffffffff83116100f75760200182360381136100f7579190565b61171d611670565b6116dc565b81601f820112156100f75780359061173982610234565b9261174760405194856101a3565b828452602083830101116100f757816000926020809301838601378301015290565b35906101d282610404565b9060a0828203126100f75781359067ffffffffffffffff82116100f75761179c918301611722565b9160208201356117ab81610404565b916040810135916080606083013592013590565b156117c657565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606490fd5b801515036100f757565b908160209103126100f75751611819816117fa565b90565b506040513d6000823e3d90fd5b908160209103126100f7575190565b6020815260a06080611855845183602086015260c0850190610303565b936001600160a01b03602082015116604085015260408101516060850152606081015182850152015191015290565b60209067ffffffffffffffff811161189d5760051b0190565b6116a061014f565b9160a0838303126100f7578235926020928382013593604083013567ffffffffffffffff81116100f75783019180601f840112156100f75782356118e881611884565b936118f660405195866101a3565b818552838086019260051b8201019283116100f7578301905b82821061192f575050505091608061192960608401611769565b92013590565b838091833561193d81610404565b81520191019061190f565b602090805115611956570190565b61166c611670565b60209081818403126100f75780519067ffffffffffffffff82116100f757019180601f840112156100f757825161199481611884565b936119a260405195866101a3565b818552838086019260051b8201019283116100f7578301905b8282106119c9575050505090565b815181529083019083016119bb565b9291909594939560a084019084526020918285015260a0604085015282518091528160c0850193019160005b828110611a265750505050906001600160a01b03608092951660608201520152565b83516001600160a01b031685529381019392810192600101611a04565b359060ff821682036100f757565b91908260c09103126100f7578135611a6881610404565b91611a7560208201611a43565b91611a8260408301611a43565b9160608101359160a0608083013592013590565b908160e09103126100f7578035611aac81610404565b916020820135611abb81610404565b91611ac860408201611a43565b91611ad560608301611a43565b9160808101359160c060a083013592013590565b908160209103126100f7575161181981610404565b9060e0828203126100f7578135926020830135611b1a81610404565b926040810135611b2981610404565b926060820135611b3881610404565b9260808301359260a08101359260c082013567ffffffffffffffff81116100f7576118199201611722565b9491611be393611bc66001600160a01b039260406118199a9895611b9b8b8251602080916001600160a01b0381511684520151910152565b6020818101518c84015291015160608b015281516001600160a01b031660808b0152015160a0890152565b1660c086015260e085015261014080610100860152840190610303565b91610120818403910152610303565b908160209103126100f7573590565b15611c0857565b60405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152606490fd5b91908260809103126100f7578135611c6481610404565b916020810135611c7381610404565b9160606040830135920135611819816117fa565b908160609103126100f7578035611c9d81610404565b9160406020830135611cae81610404565b920135611819816117fa565b60405162415c3360e91b815260ff929092166004830152602092611d83928492906001600160a01b0390848160248160008688165af1908115611e03575b600091611de6575b5060405163095ea7b360e01b8082526001600160a01b03949094166004820152602481018590529116919084816044816000875af18015611dd9575b611dbc575b506000611d59610a9d6003546001600160a01b031690565b6040519283526001600160a01b031660048301526024820193909352938492839182906044820190565b03925af18015611daf575b611d96575050565b81611dac92903d10610e9d57610e8e81836101a3565b50565b611db761181c565b611d8e565b611dd290853d8711610e9d57610e8e81836101a3565b5038611d41565b611de161181c565b611d3c565b611dfd9150853d8711610ed757610ec981836101a3565b38611d00565b611e0b61181c565b611cf8565b6000549060ff8260081c16156106eb576080816101d29362010000600160b01b0360606106cf95015160101b169062010000600160b01b031916176000556001600160a01b038151166001600160a01b0319600154161760015561068e61067260208301516001600160a01b031690565b906014825110611ea757602082015160601c916028815110611ea7576034015160601c90565b60405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606490fd5b805180601319810111611f0d575b80825110611ea75701600c015160601c90565b611f1561163d565b611efa565b3d15611f45573d90611f2b82610234565b91611f3960405193846101a3565b82523d6000602084013e565b606090565b60405163a9059cbb60e01b602082019081526001600160a01b03909316602482015260448101939093526000928392908390611f898160648101610c77565b51925af1611f95611f1a565b81611fe8575b5015611fa357565b60405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606490fd5b8051801592508215611ffd575b505038611f9b565b6120109250602080918301019101611804565b3880611ff5565b60008080938193826040516020810181811067ffffffffffffffff8211176120a1575b604052525af1612048611f1a565b501561205057565b60405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608490fd5b6120a961014f565b61203a56fea26469706673582212203cf44c3f697388a70976fd2d11d896e3dfb6e7d9adb1fc235f9e275e8fd9ae0664736f6c63430008110033
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c80630dc91306146100e357806312261ee7146100da578063156e2152146100d15780632c03ae6a146100c85780633fc8cef3146100bf5780634c3677c8146100b65780638f656d22146100ad5780638f8dc10a146100a4578063d7f478ee1461009b5763ff08da6e0361000e57610096610775565b61000e565b506100966105f2565b506100966105ca565b50610096610482565b506100966103dc565b506100966103b4565b50610096610378565b50610096610343565b50610096610124565b506100966100fc565b60009103126100f757565b600080fd5b50346100f75760003660031901126100f75760206001600160a01b0360015416604051908152f35b50346100f75760003660031901126100f75760206001600160a01b0360005460101c16604051908152f35b50634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761018257604052565b61018a61014f565b604052565b67ffffffffffffffff811161018257604052565b90601f8019910116810190811067ffffffffffffffff82111761018257604052565b604051906101d282610166565b565b604051906040820182811067ffffffffffffffff82111761018257604052565b604051906060820182811067ffffffffffffffff82111761018257604052565b604051906020820182811067ffffffffffffffff82111761018257604052565b60209067ffffffffffffffff8111610252575b601f01601f19160190565b61025a61014f565b610247565b604051906080820182811067ffffffffffffffff8211176102f6575b604052605382527f746e6573732861646472657373207573657229000000000000000000000000006060837f5769746e657373207769746e65737329546f6b656e5065726d697373696f6e7360208201527f286164647265737320746f6b656e2c75696e7432353620616d6f756e7429576960408201520152565b6102fe61014f565b61027b565b919082519283825260005b84811061032f575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161030e565b50346100f75760003660031901126100f75761037461036061025f565b604051918291602083526020830190610303565b0390f35b50346100f75760003660031901126100f75760206040517ffeed45b61d43f452c933000e813412318e408c352e137cba26cfbe202b355c3a8152f35b50346100f75760003660031901126100f75760206001600160a01b0360045416604051908152f35b50346100f75760003660031901126100f75760206001600160a01b0360035416604051908152f35b6001600160a01b038116036100f757565b60a09060031901126100f75760405161042d81610166565b60043561043981610404565b815260243561044781610404565b602082015260443561045881610404565b604082015260643561046981610404565b606082015260843561047a81610404565b608082015290565b50346100f75761049136610415565b6000549060ff8260081c1615809281936105bc575b811561059c575b5015610531576104d390826104ca600160ff196000541617600055565b61051857611e10565b6104d957005b6104e961ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b61052c61010061ff00196000541617600055565b611e10565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b303b159150816105ae575b50386104ad565b6001915060ff1614386105a7565b600160ff82161091506104a6565b50346100f75760003660031901126100f75760206001600160a01b0360025416604051908152f35b50346100f75761060136610415565b6000549060ff8260081c16156106eb576080816100199362010000600160b01b0360606106cf95015160101b169062010000600160b01b031916176000556001600160a01b038151166001600160a01b0319600154161760015561068e61067260208301516001600160a01b031690565b6001600160a01b03166001600160a01b03196002541617600255565b6106c16106a560408301516001600160a01b031690565b6001600160a01b03166001600160a01b03196003541617600355565b01516001600160a01b031690565b6001600160a01b03166001600160a01b03196004541617600455565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b9181601f840112156100f75782359167ffffffffffffffff83116100f7576020808501948460051b0101116100f757565b5060403660031901126100f75767ffffffffffffffff6004358181116100f7576107a3903690600401610744565b916024359081116100f7576107bc903690600401610744565b906107c9600a8510611597565b6107d48285146115e3565b60005b8481106107e057005b6107f36107ee828787611687565b6116c5565b6107fc816116a5565b15611473575b6108106107ee828787611687565b610819816116a5565b600180911461131b575b506108326107ee828787611687565b61083b816116a5565b60028091146111e7575b60036108556107ee848989611687565b61085e816116a5565b1461109a575b5060096108756107ee838888611687565b61087e816116a5565b14610fda575b600b6108946107ee838888611687565b61089d816116a5565b14610eeb575b600a6108b36107ee838888611687565b6108bc816116a5565b14610cf6575b60046108d26107ee838888611687565b6108db816116a5565b14610b92575b60056108f16107ee838888611687565b6108fa816116a5565b14610b12575b60066109106107ee838888611687565b610919816116a5565b14610a71575b8060086109336107ee610966948989611687565b61093c816116a5565b14610a23575b60076109526107ee838989611687565b61095b816116a5565b1461096b575b611654565b6107d7565b6109816109798286866116d2565b810190611c87565b916001600160a01b0380911691169161099b8315156117bf565b156109ac5750610961904790612017565b6040516370a0823160e01b81523060048201526109619260209290918381602481855afa938415610a16575b6000946109e7575b5050611f4a565b610a07929450803d10610a0f575b6109ff81836101a3565b810190611829565b9138806109e0565b503d6109f5565b610a1e61181c565b6109d8565b610a39610a318286866116d2565b810190611c4d565b90916001600160a01b0380911691610a528315156117bf565b15610a675750610a629250612017565b610942565b610a629316611f4a565b610a87610a7f8285856116d2565b810190611bf2565b90610aa9610a9d6004546001600160a01b031690565b6001600160a01b031690565b91823b156100f757604051632e1a7d4d60e01b81526004810191909152610966926000908290602490829084905af18015610b05575b610aec575b50905061091f565b80610af9610aff9261018f565b806100ec565b38610ae4565b610b0d61181c565b610adf565b610b20610a7f8285856116d2565b610b2c81471015611c01565b610b41610a9d6004546001600160a01b031690565b803b156100f757600090600460405180948193630d0e30db60e41b83525af18015610b85575b610b72575b50610900565b80610af9610b7f9261018f565b38610b6c565b610b8d61181c565b610b67565b610c77610c85610bae610ba68487876116d2565b810190611afe565b9792909596919450610c31610bd2610a9d6000546001600160a01b039060101c1690565b91610bdb6101d4565b6001600160a01b03918216815297816020948b868c01521697610bfc6101f4565b998a52848a01526040890152610c106101d4565b30815298838a0152610c20610214565b951685906001600160a01b03169052565b6040519283918201948591909160206001600160a01b0360408301947ffeed45b61d43f452c933000e813412318e408c352e137cba26cfbe202b355c3a84525116910152565b03601f1981018352826101a3565b51902091610c9161025f565b94823b156100f757600094610cc08692604051988997889687956309be14ff60e11b8752339160048801611b63565b03925af18015610ce9575b610cd6575b506108e1565b80610af9610ce39261018f565b38610cd0565b610cf161181c565b610ccb565b610d018184846116d2565b8101610d0c91611a96565b60405162415c3360e91b815260ff861660048201529295939493869390916001600160a01b038916826024815a602094600091f1938415986001600160a01b0398610db360208b99600099610e3598839f610ede575b8b91610eb1575b50610d7f610a9d6003546001600160a01b031690565b8b8d60405180978196829563095ea7b360e01b845260048401602090939291936001600160a01b0360408201951681520152565b0393165af18015610ea4575b610e77575b50610dda610a9d6003546001600160a01b031690565b986040519c8d9b8c9a8b99637fcb499160e11b8b52169116600489019360ff60c0969399989794819360e088019b6001600160a01b038092168952166020880152166040860152166060840152608083015260a08201520152565b03925af18015610e6a575b610e4b575b506108c2565b610e639060203d602011610a0f576109ff81836101a3565b5038610e45565b610e7261181c565b610e40565b610e96908c3d8e11610e9d575b610e8e81836101a3565b810190611804565b5038610dc4565b503d610e84565b610eac61181c565b610dbf565b610ed19150833d8511610ed7575b610ec981836101a3565b810190611ae9565b38610d69565b503d610ebf565b610ee661181c565b610d62565b6000610f03610efb8386866116d2565b810190611a96565b610f986001600160a01b03989294959397969880991691610f25898685611cba565b610f3a610a9d6003546001600160a01b031690565b95604051998a98899788966338c7897360e01b885260209e8f9d16600489019360ff60c0969399989794819360e088019b6001600160a01b038092168952166020880152166040860152166060840152608083015260a08201520152565b03925af18015610fcd575b610faf575b50506108a3565b81610fc592903d10610a0f576109ff81836101a3565b503880610fa8565b610fd561181c565b610fa3565b60006110586001600160a01b03610ffd610ff58588886116d2565b810190611a51565b94979193959092971692611012818786611cba565b604051968795869485936348b4aac360e11b855260209b8c9a60048701919260ff60809497969592978160a0860199168552166020840152604083015260608201520152565b03925af1801561108d575b61106f575b5050610884565b8161108592903d10610a0f576109ff81836101a3565b503880611068565b61109561181c565b611063565b60006001600160a01b0361117c610a9d8361115e6110c46110bc898c8c6116d2565b8101906118a5565b9793949296919816996110d88b15156117bf565b866110f8610a9d610a9d6110eb8d611948565b516001600160a01b031690565b61110c610a9d84546001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b039190911660048201526024810192909252602091908290829060449082908c905af180156111da575b6111bc575b5050546001600160a01b031690565b9460405198899788968795634401edf760e11b8752600487016119d8565b03925af180156111af575b15610864576111a8903d806000833e6111a081836101a3565b81019061195e565b5038610864565b6111b761181c565b611187565b816111d292903d10610e9d57610e8e81836101a3565b50388061114f565b6111e261181c565b61114a565b6000806001600160a01b036112006110bc8689896116d2565b9396919416956112118715156117bf565b80611224610a9d610a9d6110eb89611948565b611238610a9d8b546001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b0391909116600482015260248101929092526020919082908290604490829088905af1801561130e575b6112f0575b50506112b2611294610a9d8a546001600160a01b031690565b94604051988997889687956338ed173960e01b8752600487016119d8565b03925af180156112e3575b6112c8575b50610845565b6112dc903d806000833e6111a081836101a3565b50386112c2565b6112eb61181c565b6112bd565b8161130692903d10610e9d57610e8e81836101a3565b50388061127b565b61131661181c565b611276565b6113268285856116d2565b810161133191611774565b91949390926001600160a01b03169061134b8215156117bf565b61135481611eec565b855460405163095ea7b360e01b81526001600160a01b03918216600482015260248101869052602098899791969391929091889188916044918391165a90600091f18015610a9d60009a611408996113dd946113c294611466575b611449575b50546001600160a01b031690565b956113cb6101c5565b9586526001600160a01b031688860152565b604084015260608301526080820152604051948580948193631e51809360e31b835260048301611838565b03925af1801561143c575b61141e575b50610823565b8161143492903d10610a0f576109ff81836101a3565b503880611418565b61144461181c565b611413565b61145f908c8d3d10610e9d57610e8e81836101a3565b50386113b4565b61146e61181c565b6113af565b61147e8184846116d2565b810161148991611774565b9092936001600160a01b03809516908115156114a4906117bf565b6114ad81611e81565b509260019586546114c4906001600160a01b031690565b60405163095ea7b360e01b81526001600160a01b039190911660048201526024810182905260209889979196889188916044918391165a90600091f18015610a9d60009a6115559961152a946113c294611466576114495750546001600160a01b031690565b60408401526060830152608082015260405194858094819363c04b8d5960e01b835260048301611838565b03925af1801561158a575b61156c575b5050610802565b8161158292903d10610a0f576109ff81836101a3565b503880611565565b61159261181c565b611560565b1561159e57565b60405162461bcd60e51b815260206004820152601f60248201527f546f6f206d616e7920636f6d6d616e647320666f72206578656375746f722e006044820152606490fd5b156115ea57565b60405162461bcd60e51b815260206004820152602560248201527f416d6f756e74206f6620636f6d6d616e6473206d757374206d6174636820696e604482015264383aba399760d91b6064820152608490fd5b50634e487b7160e01b600052601160045260246000fd5b6001906000198114611664570190565b61166c61163d565b0190565b50634e487b7160e01b600052603260045260246000fd5b9190811015611698575b60051b0190565b6116a0611670565b611691565b600c11156116af57565b634e487b7160e01b600052602160045260246000fd5b35600c8110156100f75790565b9190811015611715575b60051b81013590601e19813603018212156100f757019081359167ffffffffffffffff83116100f75760200182360381136100f7579190565b61171d611670565b6116dc565b81601f820112156100f75780359061173982610234565b9261174760405194856101a3565b828452602083830101116100f757816000926020809301838601378301015290565b35906101d282610404565b9060a0828203126100f75781359067ffffffffffffffff82116100f75761179c918301611722565b9160208201356117ab81610404565b916040810135916080606083013592013590565b156117c657565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606490fd5b801515036100f757565b908160209103126100f75751611819816117fa565b90565b506040513d6000823e3d90fd5b908160209103126100f7575190565b6020815260a06080611855845183602086015260c0850190610303565b936001600160a01b03602082015116604085015260408101516060850152606081015182850152015191015290565b60209067ffffffffffffffff811161189d5760051b0190565b6116a061014f565b9160a0838303126100f7578235926020928382013593604083013567ffffffffffffffff81116100f75783019180601f840112156100f75782356118e881611884565b936118f660405195866101a3565b818552838086019260051b8201019283116100f7578301905b82821061192f575050505091608061192960608401611769565b92013590565b838091833561193d81610404565b81520191019061190f565b602090805115611956570190565b61166c611670565b60209081818403126100f75780519067ffffffffffffffff82116100f757019180601f840112156100f757825161199481611884565b936119a260405195866101a3565b818552838086019260051b8201019283116100f7578301905b8282106119c9575050505090565b815181529083019083016119bb565b9291909594939560a084019084526020918285015260a0604085015282518091528160c0850193019160005b828110611a265750505050906001600160a01b03608092951660608201520152565b83516001600160a01b031685529381019392810192600101611a04565b359060ff821682036100f757565b91908260c09103126100f7578135611a6881610404565b91611a7560208201611a43565b91611a8260408301611a43565b9160608101359160a0608083013592013590565b908160e09103126100f7578035611aac81610404565b916020820135611abb81610404565b91611ac860408201611a43565b91611ad560608301611a43565b9160808101359160c060a083013592013590565b908160209103126100f7575161181981610404565b9060e0828203126100f7578135926020830135611b1a81610404565b926040810135611b2981610404565b926060820135611b3881610404565b9260808301359260a08101359260c082013567ffffffffffffffff81116100f7576118199201611722565b9491611be393611bc66001600160a01b039260406118199a9895611b9b8b8251602080916001600160a01b0381511684520151910152565b6020818101518c84015291015160608b015281516001600160a01b031660808b0152015160a0890152565b1660c086015260e085015261014080610100860152840190610303565b91610120818403910152610303565b908160209103126100f7573590565b15611c0857565b60405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152606490fd5b91908260809103126100f7578135611c6481610404565b916020810135611c7381610404565b9160606040830135920135611819816117fa565b908160609103126100f7578035611c9d81610404565b9160406020830135611cae81610404565b920135611819816117fa565b60405162415c3360e91b815260ff929092166004830152602092611d83928492906001600160a01b0390848160248160008688165af1908115611e03575b600091611de6575b5060405163095ea7b360e01b8082526001600160a01b03949094166004820152602481018590529116919084816044816000875af18015611dd9575b611dbc575b506000611d59610a9d6003546001600160a01b031690565b6040519283526001600160a01b031660048301526024820193909352938492839182906044820190565b03925af18015611daf575b611d96575050565b81611dac92903d10610e9d57610e8e81836101a3565b50565b611db761181c565b611d8e565b611dd290853d8711610e9d57610e8e81836101a3565b5038611d41565b611de161181c565b611d3c565b611dfd9150853d8711610ed757610ec981836101a3565b38611d00565b611e0b61181c565b611cf8565b6000549060ff8260081c16156106eb576080816101d29362010000600160b01b0360606106cf95015160101b169062010000600160b01b031916176000556001600160a01b038151166001600160a01b0319600154161760015561068e61067260208301516001600160a01b031690565b906014825110611ea757602082015160601c916028815110611ea7576034015160601c90565b60405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606490fd5b805180601319810111611f0d575b80825110611ea75701600c015160601c90565b611f1561163d565b611efa565b3d15611f45573d90611f2b82610234565b91611f3960405193846101a3565b82523d6000602084013e565b606090565b60405163a9059cbb60e01b602082019081526001600160a01b03909316602482015260448101939093526000928392908390611f898160648101610c77565b51925af1611f95611f1a565b81611fe8575b5015611fa357565b60405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606490fd5b8051801592508215611ffd575b505038611f9b565b6120109250602080918301019101611804565b3880611ff5565b60008080938193826040516020810181811067ffffffffffffffff8211176120a1575b604052525af1612048611f1a565b501561205057565b60405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608490fd5b6120a961014f565b61203a56fea26469706673582212203cf44c3f697388a70976fd2d11d896e3dfb6e7d9adb1fc235f9e275e8fd9ae0664736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.