// SPDX-License-Identifier: GPL-2.0-or-later/*
* @title Solidity Bytes Arrays Utils
* @author Gonçalo Sá <goncalo.sa@consensys.net>
*
* @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.
*/pragmasolidity ^0.8.0;libraryBytesLib{
functionslice(bytesmemory _bytes,
uint256 _start,
uint256 _length
) internalpurereturns (bytesmemory) {
require(_length +31>= _length, "slice_overflow");
require(_start + _length >= _start, "slice_overflow");
require(_bytes.length>= _start + _length, "slice_outOfBounds");
bytesmemory tempBytes;
assembly {
switchiszero(_length)
case0 {
// 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 nowmstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length arraydefault {
tempBytes :=mload(0x40)
//zero out the 32 bytes slice we are about to return//we need to do it because Solidity does not garbage collectmstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
functiontoAddress(bytesmemory _bytes, uint256 _start) internalpurereturns (address) {
require(_start +20>= _start, "toAddress_overflow");
require(_bytes.length>= _start +20, "toAddress_outOfBounds");
address tempAddress;
assembly {
tempAddress :=div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
functiontoUint24(bytesmemory _bytes, uint256 _start) internalpurereturns (uint24) {
require(_start +3>= _start, "toUint24_overflow");
require(_bytes.length>= _start +3, "toUint24_outOfBounds");
uint24 tempUint;
assembly {
tempUint :=mload(add(add(_bytes, 0x3), _start))
}
return tempUint;
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 4 of 23: IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address to, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom,
address to,
uint256 amount
) externalreturns (bool);
}
Contract Source Code
File 5 of 23: IERC20PermitAllowed.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity >=0.5.0;/// @title Interface for permit/// @notice Interface used by DAI/CHAI for permitinterfaceIERC20PermitAllowed{
/// @notice Approve the spender to spend some tokens via the holder signature/// @dev This is the permit interface used by DAI and CHAI/// @param holder The address of the token holder, the token owner/// @param spender The address of the token spender/// @param nonce The holder's nonce, increases at each call to permit/// @param expiry The timestamp at which the permit is no longer valid/// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`functionpermit(address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
Contract Source Code
File 6 of 23: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)pragmasolidity ^0.8.0;import"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytescalldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/functionapprove(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
}
Contract Source Code
File 7 of 23: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)pragmasolidity ^0.8.0;import"../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/interfaceIERC721EnumerableisIERC721{
/**
* @dev Returns the total amount of tokens stored by the contract.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) externalviewreturns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/functiontokenByIndex(uint256 index) externalviewreturns (uint256);
}
Contract Source Code
File 8 of 23: IFactory.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"../interfaces/IPool.sol";
import"../interfaces/IPosition.sol";
interfaceIFactory{
eventPoolCreated(address poolAddress,
uint256 fee,
uint256 tickSpacing,
int32 activeTick,
int256 lookback,
uint64 protocolFeeRatio,
IERC20 tokenA,
IERC20 tokenB
);
eventSetFactoryProtocolFeeRatio(uint64 protocolFeeRatio);
eventSetFactoryOwner(address owner);
/// @notice creates new pool/// @param _fee is a rate in prbmath 60x18 decimal format/// @param _tickSpacing 1.0001^tickSpacing is the bin width/// @param _activeTick initial activeTick of the pool/// @param _lookback TWAP lookback in whole seconds/// @param _tokenA ERC20 token/// @param _tokenB ERC20 tokenfunctioncreate(uint256 _fee,
uint256 _tickSpacing,
int256 _lookback,
int32 _activeTick,
IERC20 _tokenA,
IERC20 _tokenB
) externalreturns (IPool);
functionlookup(uint256 fee,
uint256 tickSpacing,
int256 lookback,
IERC20 tokenA,
IERC20 tokenB
) externalviewreturns (IPool);
functionowner() externalviewreturns (address);
functionposition() externalviewreturns (IPosition);
/// @notice protocolFeeRatio ratio of the swap fee that is kept for the//protocolfunctionprotocolFeeRatio() externalviewreturns (uint64);
/// @notice lookup table for whether a pool is owned by the factoryfunctionisFactoryPool(IPool pool) externalviewreturns (bool);
}
Contract Source Code
File 9 of 23: IMulticall.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity >=0.7.5;pragmaabicoderv2;/// @title Multicall interface/// @notice Enables calling multiple methods in a single call to the contractinterfaceIMulticall{
/// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed/// @dev The `msg.value` should not be trusted for any method callable from multicall./// @param data The encoded function data for each of the calls to make to this contract/// @return results The results from each of the calls passed in via datafunctionmulticall(bytes[] calldata data) externalpayablereturns (bytes[] memory results);
}
Contract Source Code
File 10 of 23: IPool.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"./IFactory.sol";
interfaceIPool{
eventSwap(address sender,
address recipient,
bool tokenAIn,
bool exactOutput,
uint256 amountIn,
uint256 amountOut,
int32 activeTick
);
eventAddLiquidity(addressindexed sender, uint256indexed tokenId, BinDelta[] binDeltas);
eventMigrateBinsUpStack(addressindexed sender, uint128 binId, uint32 maxRecursion);
eventTransferLiquidity(uint256 fromTokenId, uint256 toTokenId, RemoveLiquidityParams[] params);
eventRemoveLiquidity(addressindexed sender,
addressindexed recipient,
uint256indexed tokenId,
BinDelta[] binDeltas
);
eventBinMerged(uint128indexed binId, uint128 reserveA, uint128 reserveB, uint128 mergeId);
eventBinMoved(uint128indexed binId, int128 previousTick, int128 newTick);
eventProtocolFeeCollected(uint256 protocolFee, bool isTokenA);
eventSetProtocolFeeRatio(uint256 protocolFee);
/// @notice return parameters for Add/Remove liquidity/// @param binId of the bin that changed/// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)/// @param isActive bool to indicate whether the bin is still active/// @param lowerTick is the lower price tick of the bin in its current state/// @param deltaA amount of A token that has been added or removed/// @param deltaB amount of B token that has been added or removed/// @param deltaLpToken amount of LP balance that has increase (add) or decreased (remove)structBinDelta {
uint128 deltaA;
uint128 deltaB;
uint256 deltaLpBalance;
uint128 binId;
uint8 kind;
int32 lowerTick;
bool isActive;
}
/// @notice time weighted average state/// @param twa the twa at the last update instant/// @param value the new value that was passed in at the last update/// @param lastTimestamp timestamp of the last update in seconds/// @param lookback time in secondsstructTwaState {
int96 twa;
int96 value;
uint64 lastTimestamp;
}
/// @notice bin state parameters/// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)/// @param lowerTick is the lower price tick of the bin in its current state/// @param mergeId binId of the bin that this bin has merged in to/// @param reserveA amount of A token in bin/// @param reserveB amount of B token in bin/// @param totalSupply total amount of LP tokens in this bin/// @param mergeBinBalance LP token balance that this bin posseses of the merge binstructBinState {
uint128 reserveA;
uint128 reserveB;
uint128 mergeBinBalance;
uint128 mergeId;
uint128 totalSupply;
uint8 kind;
int32 lowerTick;
}
/// @notice Parameters for each bin that will get new liquidity/// @param kind one of the 4 Kinds (0=static, 1=right, 2=left, 3=both)/// @param pos bin position/// @param isDelta bool that indicates whether the bin position is relative//to the current bin or an absolute position/// @param deltaA amount of A token to add/// @param deltaB amount of B token to addstructAddLiquidityParams {
uint8 kind;
int32 pos;
bool isDelta;
uint128 deltaA;
uint128 deltaB;
}
/// @notice Parameters for each bin that will have liquidity removed/// @param binId index of the bin losing liquidity/// @param amount LP balance amount to removestructRemoveLiquidityParams {
uint128 binId;
uint128 amount;
}
/// @notice State of the pool/// @param activeTick current bin position that contains the active bins/// @param status pool status. e.g. locked or unlocked; status values//defined in Pool.sol/// @param binCounter index of the last bin created/// @param protocolFeeRatio ratio of the swap fee that is kept for the//protocolstructState {
int32 activeTick;
uint8 status;
uint128 binCounter;
uint64 protocolFeeRatio;
}
/// @notice fee for pool in 18 decimal formatfunctionfee() externalviewreturns (uint256);
/// @notice tickSpacing of pool where 1.0001^tickSpacing is the bin widthfunctiontickSpacing() externalviewreturns (uint256);
/// @notice address of token AfunctiontokenA() externalviewreturns (IERC20);
/// @notice address of token BfunctiontokenB() externalviewreturns (IERC20);
/// @notice address of Factoryfunctionfactory() externalviewreturns (IFactory);
/// @notice bitmap of active binsfunctionbinMap(int32 tick) externalviewreturns (uint256);
/// @notice mapping of tick/kind to binIdfunctionbinPositions(int32 tick, uint256 kind) externalviewreturns (uint128);
/// @notice internal accounting of the sum tokenA balance across binsfunctionbinBalanceA() externalviewreturns (uint128);
/// @notice internal accounting of the sum tokenB balance across binsfunctionbinBalanceB() externalviewreturns (uint128);
/// @notice log_binWidth of the time weighted average pricefunctiongetTwa() externalviewreturns (TwaState memory);
/// @notice pool statefunctiongetState() externalviewreturns (State memory);
/// @notice Add liquidity to a pool./// @param tokenId NFT token ID that will hold the position/// @param params array of AddLiquidityParams that specify the mode and//position of the liquidity/// @param data callback function that addLiquidity will call so that the//caller can transfer tokensfunctionaddLiquidity(uint256 tokenId,
AddLiquidityParams[] calldata params,
bytescalldata data
)
externalreturns (uint256 tokenAAmount,
uint256 tokenBAmount,
BinDelta[] memory binDeltas
);
/// @notice Transfer liquidity in an array of bins from one nft tokenId//to another/// @param fromTokenId NFT token ID that holds the position being transferred/// @param toTokenId NFT token ID that is receiving liquidity/// @param params array of binIds and amounts to transferfunctiontransferLiquidity(uint256 fromTokenId,
uint256 toTokenId,
RemoveLiquidityParams[] calldata params
) external;
/// @notice Remove liquidity from a pool./// @param recipient address that will receive the removed tokens/// @param tokenId NFT token ID that holds the position being removed/// @param params array of RemoveLiquidityParams that specify the bins,//and amountsfunctionremoveLiquidity(address recipient,
uint256 tokenId,
RemoveLiquidityParams[] calldata params
)
externalreturns (uint256 tokenAOut,
uint256 tokenBOut,
BinDelta[] memory binDeltas
);
/// @notice Migrate bins up the linked list of merged bins so that its//mergeId is the currrent active bin./// @param binId is an array of the binIds to be migrated/// @param maxRecursion is the maximum recursion depth of the migration. set to//zero to recurse until the active bin is found.functionmigrateBinUpStack(uint128 binId, uint32 maxRecursion) external;
/// @notice swap tokens/// @param recipient address that will receive the output tokens/// @param amount amount of token that is either the input if exactOutput//is false or the output if exactOutput is true/// @param tokenAIn bool indicating whether tokenA is the input/// @param exactOutput bool indicating whether the amount specified is the//exact output amount (true)/// @param sqrtPriceLimit limiting sqrt price of the swap. A value of 0//indicates no limit. Limit is only engaged for exactOutput=false. If the//limit is reached only part of the input amount will be swapped and the//callback will only require that amount of the swap to be paid./// @param data callback function that swap will call so that the//caller can transfer tokensfunctionswap(address recipient,
uint256 amount,
bool tokenAIn,
bool exactOutput,
uint256 sqrtPriceLimit,
bytescalldata data
) externalreturns (uint256 amountIn, uint256 amountOut);
/// @notice bin information for a given binIdfunctiongetBin(uint128 binId) externalviewreturns (BinState memory bin);
/// @notice LP token balance for a given tokenId at a given binIdfunctionbalanceOf(uint256 tokenId, uint128 binId) externalviewreturns (uint256 lpToken);
/// @notice tokenA scale value/// @dev msb is a flag to indicate whether tokenA has more or less than 18//decimals. Scale is used in conjuction with Math.toScale/Math.fromScale//functions to convert from token amounts to D18 scale internal pool//accounting.functiontokenAScale() externalviewreturns (uint256);
/// @notice tokenB scale value/// @dev msb is a flag to indicate whether tokenA has more or less than 18//decimals. Scale is used in conjuction with Math.toScale/Math.fromScale//functions to convert from token amounts to D18 scale internal pool//accounting.functiontokenBScale() externalviewreturns (uint256);
}
Contract Source Code
File 11 of 23: IPosition.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import"../interfaces/IPositionMetadata.sol";
interfaceIPositionisIERC721Enumerable{
eventSetMetadata(IPositionMetadata metadata);
/// @notice mint new position NFTfunctionmint(address to) externalreturns (uint256 tokenId);
/// @notice mint new position NFTfunctiontokenOfOwnerByIndexExists(address owner, uint256 index) externalviewreturns (bool);
}
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"@maverick/contracts/contracts/interfaces/IFactory.sol";
import"@maverick/contracts/contracts/interfaces/IPool.sol";
import"@maverick/contracts/contracts/interfaces/IPosition.sol";
import"@maverick/contracts/contracts/interfaces/ISwapCallback.sol";
import"./external/IWETH9.sol";
import"./ISlimRouter.sol";
interfaceIRouterisISlimRouter{
/// @return Returns the address of the factoryfunctionfactory() externalviewreturns (IFactory);
/// @return Returns the address of the Position NFTfunctionposition() externalviewreturns (IPosition);
structExactInputParams {
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 tokenfunctionexactInput(
ExactInputParams calldata params
) externalpayablereturns (uint256 amountOut);
structExactOutputParams {
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 tokenfunctionexactOutput(
ExactOutputParams calldata params
) externalpayablereturns (uint256 amountIn);
structPoolParams {
uint256 fee;
uint256 tickSpacing;
int256 lookback;
int32 activeTick;
IERC20 tokenA;
IERC20 tokenB;
}
/// @notice create a pool and add liquidity to it/// @param poolParams paramters of a pool/// @param tokenId nft id of token that will hold lp balance, use 0 to mint a new token/// @param addParams paramters of liquidity addition/// @param minTokenAAmount minimum amount of token A to add, revert if not met/// @param minTokenBAmount minimum amount of token B to add, revert if not met/// @param deadline epoch timestamp in secondsfunctiongetOrCreatePoolAndAddLiquidity(
PoolParams calldata poolParams,
uint256 tokenId,
IPool.AddLiquidityParams[] calldata addParams,
uint256 minTokenAAmount,
uint256 minTokenBAmount,
uint256 deadline
)
externalpayablereturns (uint256 receivingTokenId,
uint256 tokenAAmount,
uint256 tokenBAmount,
IPool.BinDelta[] memory binDeltas
);
/// @notice add liquidity to a pool/// @param pool pool to add liquidity to/// @param tokenId nft id of token that will hold lp balance, use 0 to mint a new token/// @param params paramters of liquidity addition/// @param minTokenAAmount minimum amount of token A to add, revert if not met/// @param minTokenBAmount minimum amount of token B to add, revert if not met/// @param deadline epoch timestamp in secondsfunctionaddLiquidityToPool(
IPool pool,
uint256 tokenId,
IPool.AddLiquidityParams[] calldata params,
uint256 minTokenAAmount,
uint256 minTokenBAmount,
uint256 deadline
)
externalpayablereturns (uint256 receivingTokenId,
uint256 tokenAAmount,
uint256 tokenBAmount,
IPool.BinDelta[] memory binDeltas
);
/// @notice add liquidity to a pool with active tick limits/// @param pool pool to add liquidity to/// @param tokenId nft id of token that will hold lp balance, use 0 to mint a new token/// @param params paramters of liquidity addition/// @param minTokenAAmount minimum amount of token A to add, revert if not met/// @param minTokenBAmount minimum amount of token B to add, revert if not met/// @param minActiveTick lowest activeTick (inclusive) of pool that will permit transaction to pass/// @param maxActiveTick highest activeTick (inclusive) of pool that will permit transaction to pass/// @param deadline epoch timestamp in secondsfunctionaddLiquidityWTickLimits(
IPool pool,
uint256 tokenId,
IPool.AddLiquidityParams[] calldata params,
uint256 minTokenAAmount,
uint256 minTokenBAmount,
int32 minActiveTick,
int32 maxActiveTick,
uint256 deadline
)
externalpayablereturns (uint256 receivingTokenId,
uint256 tokenAAmount,
uint256 tokenBAmount,
IPool.BinDelta[] memory binDeltas
);
/// @notice moves the head of input merged bins to the active bin/// @param pool to remove from/// @param binIds array of bin Ids to migrate/// @param maxRecursion maximum recursion depth before returning; 0=no max/// @param deadline epoch timestamp in secondsfunctionmigrateBinsUpStack(
IPool pool,
uint128[] calldata binIds,
uint32 maxRecursion,
uint256 deadline
) external;
/// @notice remove liquidity from pool and receive WETH if one of the tokens is WETH/// @dev router must be approved for the withdrawing tokenId: Position.approve(router, tokenId)/// @param pool pool to remove from/// @param recipient address where proceeds are sent; use zero or router address to leave tokens in router/// @param tokenId ID of position NFT that holds liquidity/// @param params paramters of liquidity removal/// @param minTokenAAmount minimum amount of token A to receive, revert if not met/// @param minTokenBAmount minimum amount of token B to receive, revert if not met/// @param deadline epoch timestamp in secondsfunctionremoveLiquidity(
IPool pool,
address recipient,
uint256 tokenId,
IPool.RemoveLiquidityParams[] calldata params,
uint256 minTokenAAmount,
uint256 minTokenBAmount,
uint256 deadline
)
externalreturns (uint256 tokenAAmount, uint256 tokenBAmount, IPool.BinDelta[] memory binDeltas);
}
Contract Source Code
File 14 of 23: ISelfPermit.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity >=0.7.5;/// @title Self Permit/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the routeinterfaceISelfPermit{
/// @notice Permits this contract to spend a given token from `msg.sender`/// @dev The `owner` is always msg.sender and the `spender` is always address(this)./// @param token The address of the token spent/// @param value The amount that can be spent of token/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`functionselfPermit(address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) externalpayable;
/// @notice Permits this contract to spend a given token from `msg.sender`/// @dev The `owner` is always msg.sender and the `spender` is always address(this)./// Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit/// @param token The address of the token spent/// @param value The amount that can be spent of token/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`functionselfPermitIfNecessary(address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) externalpayable;
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter/// @dev The `owner` is always msg.sender and the `spender` is always address(this)/// @param token The address of the token spent/// @param nonce The current nonce of the owner/// @param expiry The timestamp at which the permit is no longer valid/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`functionselfPermitAllowed(address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) externalpayable;
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter/// @dev The `owner` is always msg.sender and the `spender` is always address(this)/// Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed./// @param token The address of the token spent/// @param nonce The current nonce of the owner/// @param expiry The timestamp at which the permit is no longer valid/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`functionselfPermitAllowedIfNecessary(address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) externalpayable;
}
Contract Source Code
File 15 of 23: ISlimRouter.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"@maverick/contracts/contracts/interfaces/IFactory.sol";
import"@maverick/contracts/contracts/interfaces/IPool.sol";
import"@maverick/contracts/contracts/interfaces/IPosition.sol";
import"@maverick/contracts/contracts/interfaces/ISwapCallback.sol";
import"./external/IWETH9.sol";
interfaceISlimRouterisISwapCallback{
/// @return Returns the address of WETH9functionWETH9() externalviewreturns (IWETH9);
structExactInputSingleParams {
address tokenIn;
address tokenOut;
IPool pool;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint256 sqrtPriceLimitD18;
}
/// @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 tokenfunctionexactInputSingle(
ExactInputSingleParams calldata params
) externalpayablereturns (uint256 amountOut);
structExactOutputSingleParams {
address tokenIn;
address tokenOut;
IPool pool;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @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 tokenfunctionexactOutputSingle(
ExactOutputSingleParams calldata params
) externalpayablereturns (uint256 amountIn);
/// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH./// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users./// @param amountMinimum The minimum amount of WETH9 to unwrap/// @param recipient The address receiving ETHfunctionunwrapWETH9(uint256 amountMinimum, address recipient) externalpayable;
/// @notice Refunds any ETH balance held by this contract to the `msg.sender`/// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps/// that use ether for the input amountfunctionrefundETH() externalpayable;
/// @notice Transfers the full amount of a token held by this contract to recipient/// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users/// @param token The contract address of the token which will be transferred to `recipient`/// @param amountMinimum The minimum amount of token required for a transfer/// @param recipient The destination address of the tokenfunctionsweepToken(IERC20 token, uint256 amountMinimum, address recipient) externalpayable;
}
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Interface for WETH9interfaceIWETH9isIERC20{
/// @notice Deposit ether to get wrapped etherfunctiondeposit() externalpayable;
/// @notice Withdraw wrapped ether to get etherfunctionwithdraw(uint256) external;
}
Contract Source Code
File 18 of 23: Multicall.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;pragmaabicoderv2;import"../interfaces/IMulticall.sol";
/// @title Multicall/// @notice Enables calling multiple methods in a single call to the contractabstractcontractMulticallisIMulticall{
/// @inheritdoc IMulticallfunctionmulticall(bytes[] calldata data
) publicpayableoverridereturns (bytes[] memory results) {
results =newbytes[](data.length);
for (uint256 i =0; i < data.length; i++) {
(bool success, bytesmemory result) =address(this).delegatecall(data[i]);
if (!success) {
// Next 5 lines from https://ethereum.stackexchange.com/a/83577if (result.length<68) revert();
assembly {
result :=add(result, 0x04)
}
revert(abi.decode(result, (string)));
}
results[i] = result;
}
}
}
Contract Source Code
File 19 of 23: Path.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"@maverick/contracts/contracts/interfaces/IPool.sol";
import"./BytesLib.sol";
/// @title Functions for manipulating path data for multihop swapslibraryPath{
usingBytesLibforbytes;
/// @dev The length of the bytes encoded addressuint256privateconstant ADDR_SIZE =20;
/// @dev The offset of a single token address and pool addressuint256privateconstant NEXT_OFFSET = ADDR_SIZE + ADDR_SIZE;
/// @dev The offset of an encoded pool keyuint256privateconstant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
/// @dev The minimum length of an encoding that contains 2 or more poolsuint256privateconstant 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 falsefunctionhasMultiplePools(bytesmemory path) internalpurereturns (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 pathfunctionnumPools(bytesmemory path) internalpurereturns (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 tokenIn The input in a path/// @return tokenOut The output in a path/// @return pool The poolfunctiondecodeFirstPool(bytesmemory path
) internalpurereturns (IERC20 tokenIn, IERC20 tokenOut, IPool pool) {
tokenIn = IERC20(path.toAddress(0));
pool = IPool(path.toAddress(ADDR_SIZE));
tokenOut = IERC20(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 pathfunctiongetFirstPool(bytesmemory path) internalpurereturns (bytesmemory) {
return path.slice(0, POP_OFFSET);
}
/// @notice Skips a token + pool element from the buffer and returns the remainder/// @param path The swap path/// @return The remaining token + pool elements in the pathfunctionskipToken(bytesmemory path) internalpurereturns (bytesmemory) {
return path.slice(NEXT_OFFSET, path.length- NEXT_OFFSET);
}
}
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity >=0.5.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import"../interfaces/ISelfPermit.sol";
import"../interfaces/external/IERC20PermitAllowed.sol";
/// @title Self Permit/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route/// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function/// that requires an approval in a single transaction.abstractcontractSelfPermitisISelfPermit{
/// @inheritdoc ISelfPermitfunctionselfPermit(address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) publicpayableoverride{
IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s);
}
/// @inheritdoc ISelfPermitfunctionselfPermitIfNecessary(address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) externalpayableoverride{
if (IERC20(token).allowance(msg.sender, address(this)) < value)
selfPermit(token, value, deadline, v, r, s);
}
/// @inheritdoc ISelfPermitfunctionselfPermitAllowed(address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) publicpayableoverride{
IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s);
}
/// @inheritdoc ISelfPermitfunctionselfPermitAllowedIfNecessary(address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) externalpayableoverride{
if (IERC20(token).allowance(msg.sender, address(this)) <type(uint256).max)
selfPermitAllowed(token, nonce, expiry, v, r, s);
}
}
Contract Source Code
File 22 of 23: TransferHelper.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity >=0.6.0;import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
libraryTransferHelper{
/// @notice Transfers tokens from the targeted address to the given destination/// @notice Errors with 'STF' if transfer fails/// @param token The contract address of the token to be transferred/// @param from The originating address from which the tokens will be transferred/// @param to The destination address of the transfer/// @param value The amount to be transferredfunctionsafeTransferFrom(address token, addressfrom, address to, uint256 value) internal{
(bool success, bytesmemory data) = token.call(
abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)
);
require(success && (data.length==0||abi.decode(data, (bool))), "STF");
}
/// @notice Transfers tokens from msg.sender to a recipient/// @dev Errors with ST if transfer fails/// @param token The contract address of the token which will be transferred/// @param to The recipient of the transfer/// @param value The value of the transferfunctionsafeTransfer(address token, address to, uint256 value) internal{
(bool success, bytesmemory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(success && (data.length==0||abi.decode(data, (bool))), "ST");
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token/// @dev Errors with 'SA' if transfer fails/// @param token The contract address of the token to be approved/// @param to The target of the approval/// @param value The amount of the given token the target will be allowed to spendfunctionsafeApprove(address token, address to, uint256 value) internal{
(bool success, bytesmemory data) = token.call(
abi.encodeWithSelector(IERC20.approve.selector, to, value)
);
require(success && (data.length==0||abi.decode(data, (bool))), "SA");
}
/// @notice Transfers ETH to the recipient address/// @dev Fails with `STE`/// @param to The destination of the transfer/// @param value The value to be transferredfunctionsafeTransferETH(address to, uint256 value) internal{
(bool success, ) = to.call{value: value}(newbytes(0));
require(success, "STE");
}
}
Contract Source Code
File 23 of 23: draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/interfaceIERC20Permit{
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/functionpermit(address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/functionnonces(address owner) externalviewreturns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/// solhint-disable-next-line func-name-mixedcasefunctionDOMAIN_SEPARATOR() externalviewreturns (bytes32);
}