Source Code
Overview
HYPE Balance
HYPE Value
$0.00Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x151cc915...b94985670 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
TransparentUpgradeableProxy
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; import "../ERC1967/ERC1967Proxy.sol"; /** * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} * does not implement this interface directly, and some of its functions are implemented by an internal dispatch * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not * include them in the ABI so this interface must be used to interact with it. */ interface ITransparentUpgradeableProxy is IERC1967 { function admin() external view returns (address); function implementation() external view returns (address); function changeAdmin(address) external; function upgradeTo(address) external; function upgradeToAndCall(address, bytes memory) external payable; } /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. * * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the * implementation. * * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. */ constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) { _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. * * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the * implementation provides a function with the same selector. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior */ function _fallback() internal virtual override { if (msg.sender == _getAdmin()) { bytes memory ret; bytes4 selector = msg.sig; if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) { ret = _dispatchUpgradeTo(); } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) { ret = _dispatchUpgradeToAndCall(); } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) { ret = _dispatchChangeAdmin(); } else if (selector == ITransparentUpgradeableProxy.admin.selector) { ret = _dispatchAdmin(); } else if (selector == ITransparentUpgradeableProxy.implementation.selector) { ret = _dispatchImplementation(); } else { revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target"); } assembly { return(add(ret, 0x20), mload(ret)) } } else { super._fallback(); } } /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function _dispatchAdmin() private returns (bytes memory) { _requireZeroValue(); address admin = _getAdmin(); return abi.encode(admin); } /** * @dev Returns the current implementation. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _dispatchImplementation() private returns (bytes memory) { _requireZeroValue(); address implementation = _implementation(); return abi.encode(implementation); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _dispatchChangeAdmin() private returns (bytes memory) { _requireZeroValue(); address newAdmin = abi.decode(msg.data[4:], (address)); _changeAdmin(newAdmin); return ""; } /** * @dev Upgrade the implementation of the proxy. */ function _dispatchUpgradeTo() private returns (bytes memory) { _requireZeroValue(); address newImplementation = abi.decode(msg.data[4:], (address)); _upgradeToAndCall(newImplementation, bytes(""), false); return ""; } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. */ function _dispatchUpgradeToAndCall() private returns (bytes memory) { (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); _upgradeToAndCall(newImplementation, data, true); return ""; } /** * @dev Returns the current admin. * * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to * emulate some proxy functions being non-payable while still allowing value to pass through. */ function _requireZeroValue() private { require(msg.value == 0); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract interface IMulticall { /// @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 data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0; interface IUniswapV2Pair { 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; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '@openzeppelin/contracts/utils/Base64.sol'; contract Base64Test { function encode(bytes memory data) external pure returns (string memory) { return Base64.encode(data); } function getGasCostOfEncode(bytes memory data) external view returns (uint256) { uint256 gasBefore = gasleft(); Base64.encode(data); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; /// @title Self Permit /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route interface ISelfPermit { /// @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` function selfPermit( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; /// @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` function selfPermitIfNecessary( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; /// @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` function selfPermitAllowed( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external payable; /// @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` function selfPermitAllowedIfNecessary( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external payable; }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; pragma abicoder v1; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; contract TestToken is ERC20 { constructor(uint256 amountToMint, string memory name, string memory symbol) ERC20(name, symbol) { _mint(msg.sender, amountToMint); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/libraries/SafeCast.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/callback/IAlgebraSwapCallback.sol'; import '../interfaces/IQuoterV2.sol'; import '../base/PeripheryImmutableState.sol'; import '../libraries/Path.sol'; import '../libraries/PoolAddress.sol'; import '../libraries/CallbackValidation.sol'; import '../libraries/PoolTicksCounter.sol'; /// @title Algebra Integral 1.2.1 QuoterV2 /// @notice Allows getting the expected amount out or amount in for a given swap without executing the swap /// @dev These functions are not gas efficient and should _not_ be called on chain. Instead, optimistically execute /// the swap and check the amounts in the callback. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract QuoterV2 is IQuoterV2, IAlgebraSwapCallback, PeripheryImmutableState { using Path for bytes; using SafeCast for uint256; using PoolTicksCounter for IAlgebraPool; /// @dev Transient storage variable used to check a safety condition in exact output swaps. uint256 private amountOutCached; constructor( address _factory, address _WNativeToken, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) {} function getPool(address deployer, address tokenA, address tokenB) private view returns (IAlgebraPool) { return IAlgebraPool(PoolAddress.computeAddress(poolDeployer, PoolAddress.getPoolKey(deployer, tokenA, tokenB))); } /// @inheritdoc IAlgebraSwapCallback function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes memory path) external view override { require(amount0Delta > 0 || amount1Delta > 0, 'Zero liquidity swap'); // swaps entirely within 0-liquidity regions are not supported (address tokenIn, address deployer, address tokenOut) = path.decodeFirstPool(); CallbackValidation.verifyCallback(poolDeployer, deployer, tokenIn, tokenOut); (bool isExactInput, uint256 amountToPay, uint256 amountReceived) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta), uint256(-amount1Delta)) : (tokenOut < tokenIn, uint256(amount1Delta), uint256(-amount0Delta)); IAlgebraPool pool = getPool(deployer, tokenIn, tokenOut); (uint160 sqrtPriceX96After, int24 tickAfter, uint16 fee, , , ) = pool.globalState(); if (isExactInput) { assembly { let ptr := mload(0x40) mstore(ptr, amountReceived) mstore(add(ptr, 0x20), amountToPay) mstore(add(ptr, 0x40), sqrtPriceX96After) mstore(add(ptr, 0x60), tickAfter) mstore(add(ptr, 0x80), fee) revert(ptr, 224) } } else { // if the cache has been populated, ensure that the full output amount has been received if (amountOutCached != 0) require(amountReceived == amountOutCached, 'Not received full amountOut'); assembly { let ptr := mload(0x40) mstore(ptr, amountReceived) mstore(add(ptr, 0x20), amountToPay) mstore(add(ptr, 0x40), sqrtPriceX96After) mstore(add(ptr, 0x60), tickAfter) mstore(add(ptr, 0x80), fee) revert(ptr, 224) } } } /// @dev Parses a revert reason that should contain the numeric quote function parseRevertReason( bytes memory reason ) private pure returns (uint256 amountReceived, uint256 amountToPay, uint160 sqrtPriceX96After, int24 tickAfter, uint16 fee) { if (reason.length != 224) { require(reason.length > 0, 'Unexpected error'); assembly ('memory-safe') { revert(add(32, reason), mload(reason)) } } return abi.decode(reason, (uint256, uint256, uint160, int24, uint16)); } function handleRevert( bytes memory reason, IAlgebraPool pool, uint256 gasEstimate ) private view returns ( uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256, uint16 fee ) { int24 tickBefore; int24 tickAfter; (, tickBefore, , , , ) = pool.globalState(); (amountOut, amountIn, sqrtPriceX96After, tickAfter, fee) = parseRevertReason(reason); initializedTicksCrossed = pool.countInitializedTicksCrossed(tickBefore, tickAfter); return (amountOut, amountIn, sqrtPriceX96After, initializedTicksCrossed, gasEstimate, fee); } function quoteExactInputSingle( QuoteExactInputSingleParams memory params ) public override returns ( uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate, uint16 fee ) { bool zeroToOne = params.tokenIn < params.tokenOut; IAlgebraPool pool = getPool(params.deployer, params.tokenIn, params.tokenOut); uint256 gasBefore = gasleft(); bytes memory data = abi.encodePacked(params.tokenIn, params.deployer, params.tokenOut); try pool.swap( address(this), // address(0) might cause issues with some tokens zeroToOne, params.amountIn.toInt256(), params.limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : params.limitSqrtPrice, data ) {} catch (bytes memory reason) { gasEstimate = gasBefore - gasleft(); return handleRevert(reason, pool, gasEstimate); } } function quoteExactInput( bytes memory path, uint256 amountInRequired ) public override returns ( uint256[] memory amountOutList, uint256[] memory amountInList, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate, uint16[] memory feeList ) { amountOutList = new uint256[](path.numPools()); amountInList = new uint256[](path.numPools()); sqrtPriceX96AfterList = new uint160[](path.numPools()); initializedTicksCrossedList = new uint32[](path.numPools()); feeList = new uint16[](path.numPools()); uint256 i = 0; while (true) { QuoteExactInputSingleParams memory params; { (address tokenIn, address deployer, address tokenOut) = path.decodeFirstPool(); params.tokenIn = tokenIn; params.deployer = deployer; params.tokenOut = tokenOut; params.amountIn = amountInRequired; } // the outputs of prior swaps become the inputs to subsequent ones uint256 _gasEstimate; ( amountOutList[i], amountInList[i], sqrtPriceX96AfterList[i], initializedTicksCrossedList[i], _gasEstimate, feeList[i] ) = quoteExactInputSingle(params); amountInRequired = amountOutList[i]; gasEstimate += _gasEstimate; i++; // decide whether to continue or terminate if (path.hasMultiplePools()) { path = path.skipToken(); } else { return ( amountOutList, amountInList, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate, feeList ); } } } function quoteExactOutputSingle( QuoteExactOutputSingleParams memory params ) public override returns ( uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate, uint16 fee ) { bool zeroToOne = params.tokenIn < params.tokenOut; IAlgebraPool pool = getPool(params.deployer, params.tokenIn, params.tokenOut); // if no price limit has been specified, cache the output amount for comparison in the swap callback if (params.limitSqrtPrice == 0) amountOutCached = params.amount; uint256 gasBefore = gasleft(); bytes memory data = abi.encodePacked(params.tokenOut, params.deployer, params.tokenIn); try pool.swap( address(this), // address(0) might cause issues with some tokens zeroToOne, -params.amount.toInt256(), params.limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : params.limitSqrtPrice, data ) {} catch (bytes memory reason) { gasEstimate = gasBefore - gasleft(); if (params.limitSqrtPrice == 0) delete amountOutCached; // clear cache return handleRevert(reason, pool, gasEstimate); } } function quoteExactOutput( bytes memory path, uint256 amountOutRequired ) public override returns ( uint256[] memory amountOutList, uint256[] memory amountInList, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate, uint16[] memory feeList ) { amountOutList = new uint256[](path.numPools()); amountInList = new uint256[](path.numPools()); sqrtPriceX96AfterList = new uint160[](path.numPools()); initializedTicksCrossedList = new uint32[](path.numPools()); feeList = new uint16[](path.numPools()); uint256 i = 0; while (true) { QuoteExactOutputSingleParams memory params; { (address tokenOut, address deployer, address tokenIn) = path.decodeFirstPool(); params.tokenIn = tokenIn; params.deployer = deployer; params.tokenOut = tokenOut; params.amount = amountOutRequired; } // the inputs of prior swaps become the outputs of subsequent ones uint256 _gasEstimate; ( amountOutList[i], amountInList[i], sqrtPriceX96AfterList[i], initializedTicksCrossedList[i], _gasEstimate, feeList[i] ) = quoteExactOutputSingle(params); amountOutRequired = amountInList[i]; gasEstimate += _gasEstimate; i++; // decide whether to continue or terminate if (path.hasMultiplePools()) { path = path.skipToken(); } else { return ( amountOutList, amountInList, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate, feeList ); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./IERC20Permit.sol";
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0 <0.9.0; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/Constants.sol'; import '../interfaces/INonfungiblePositionManager.sol'; import './LiquidityAmounts.sol'; import './PoolAddress.sol'; /// @title Returns information about the token value held in a Algebra Integral NFT /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PositionValue { struct PositionCache { address token0; address token1; address deployer; int24 tickLower; int24 tickUpper; uint128 liquidity; uint256 feeGrowthInside0LastX128; uint256 feeGrowthInside1LastX128; uint256 tokensOwed0; uint256 tokensOwed1; } /// @notice Returns the total amounts of token0 and token1, i.e. the sum of fees and principal /// that a given nonfungible position manager token is worth /// @param positionManager The Algebra NonfungiblePositionManager /// @param tokenId The tokenId of the token for which to get the total value /// @param sqrtRatioX96 The square root price X96 for which to calculate the principal amounts /// @return amount0 The total amount of token0 including principal and fees /// @return amount1 The total amount of token1 including principal and fees function total( INonfungiblePositionManager positionManager, uint256 tokenId, uint160 sqrtRatioX96 ) internal view returns (uint256 amount0, uint256 amount1) { PositionCache memory _position = _getPosition(positionManager, tokenId); (uint256 amount0Principal, uint256 amount1Principal) = _principal( sqrtRatioX96, _position.tickLower, _position.tickUpper, _position.liquidity ); (uint256 amount0Fee, uint256 amount1Fee) = _fees(positionManager, _position); return (amount0Principal + amount0Fee, amount1Principal + amount1Fee); } /// @notice Calculates the principal (currently acting as liquidity) owed to the token owner in the event /// that the position is burned /// @param positionManager The Algebra NonfungiblePositionManager /// @param tokenId The tokenId of the token for which to get the total principal owed /// @param sqrtRatioX96 The square root price X96 for which to calculate the principal amounts /// @return amount0 The principal amount of token0 /// @return amount1 The principal amount of token1 function principal( INonfungiblePositionManager positionManager, uint256 tokenId, uint160 sqrtRatioX96 ) internal view returns (uint256 amount0, uint256 amount1) { (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(tokenId); return _principal(sqrtRatioX96, tickLower, tickUpper, liquidity); } /// @notice Calculates the total fees owed to the token owner /// @param positionManager The Algebra NonfungiblePositionManager /// @param tokenId The tokenId of the token for which to get the total fees owed /// @return amount0 The amount of fees owed in token0 /// @return amount1 The amount of fees owed in token1 function fees( INonfungiblePositionManager positionManager, uint256 tokenId ) internal view returns (uint256 amount0, uint256 amount1) { return _fees(positionManager, _getPosition(positionManager, tokenId)); } function _principal( uint160 sqrtRatioX96, int24 tickLower, int24 tickUpper, uint128 liquidity ) private pure returns (uint256 amount0, uint256 amount1) { return LiquidityAmounts.getAmountsForLiquidity( sqrtRatioX96, TickMath.getSqrtRatioAtTick(tickLower), TickMath.getSqrtRatioAtTick(tickUpper), liquidity ); } function _fees( INonfungiblePositionManager positionManager, PositionCache memory position ) private view returns (uint256 amount0, uint256 amount1) { unchecked { (uint256 poolFeeGrowthInside0LastX128, uint256 poolFeeGrowthInside1LastX128) = _getFeeGrowthInside( IAlgebraPool( PoolAddress.computeAddress( positionManager.poolDeployer(), PoolAddress.PoolKey({ deployer: position.deployer, token0: position.token0, token1: position.token1 }) ) ), position.tickLower, position.tickUpper ); amount0 = FullMath.mulDiv( poolFeeGrowthInside0LastX128 - position.feeGrowthInside0LastX128, position.liquidity, Constants.Q128 ) + position.tokensOwed0; amount1 = FullMath.mulDiv( poolFeeGrowthInside1LastX128 - position.feeGrowthInside1LastX128, position.liquidity, Constants.Q128 ) + position.tokensOwed1; } } function _getPosition( INonfungiblePositionManager positionManager, uint256 tokenId ) private view returns (PositionCache memory) { ( , , address token0, address token1, address deployer, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ) = positionManager.positions(tokenId); return PositionCache( token0, token1, deployer, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1 ); } function _getFeeGrowthInside( IAlgebraPool pool, int24 bottomTick, int24 topTick ) private view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { (, int24 currentTick, , , , ) = pool.globalState(); (uint256 lowerOuterFeeGrowth0Token, uint256 lowerOuterFeeGrowth1Token) = _getOuterFeeGrowth(pool, bottomTick); (uint256 upperOuterFeeGrowth0Token, uint256 upperOuterFeeGrowth1Token) = _getOuterFeeGrowth(pool, topTick); unchecked { if (currentTick < topTick) { if (currentTick >= bottomTick) { uint256 feeGrowthGlobal0X128 = pool.totalFeeGrowth0Token(); uint256 feeGrowthGlobal1X128 = pool.totalFeeGrowth1Token(); feeGrowthInside0X128 = feeGrowthGlobal0X128 - lowerOuterFeeGrowth0Token; feeGrowthInside1X128 = feeGrowthGlobal1X128 - lowerOuterFeeGrowth1Token; } else { feeGrowthInside0X128 = lowerOuterFeeGrowth0Token; feeGrowthInside1X128 = lowerOuterFeeGrowth1Token; } feeGrowthInside0X128 -= upperOuterFeeGrowth0Token; feeGrowthInside1X128 -= upperOuterFeeGrowth1Token; } else { feeGrowthInside0X128 = upperOuterFeeGrowth0Token - lowerOuterFeeGrowth0Token; feeGrowthInside1X128 = upperOuterFeeGrowth1Token - lowerOuterFeeGrowth1Token; } } } function _getOuterFeeGrowth( IAlgebraPool pool, int24 tick ) private view returns (uint256 outerFeeGrowth0Token, uint256 OuterFeeGrowth1Token) { (, , , , outerFeeGrowth0Token, OuterFeeGrowth1Token) = pool.ticks(tick); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import {IAlgebraCustomPoolEntryPoint} from '../interfaces/IAlgebraCustomPoolEntryPoint.sol'; contract CustomPoolDeployerTest { address public immutable entryPoint; address public immutable plugin; mapping(address => address) public poolToPlugin; constructor(address _entryPoint, address _plugin) { entryPoint = _entryPoint; plugin = _plugin; } function createCustomPool( address deployer, address creator, address tokenA, address tokenB, bytes calldata data ) external returns (address customPool) { return IAlgebraCustomPoolEntryPoint(entryPoint).createCustomPool(deployer, creator, tokenA, tokenB, data); } function beforeCreatePoolHook( address, address, address, address, address, bytes calldata ) external view returns (address) { require(msg.sender == entryPoint, 'Only entryPoint'); return plugin; } function afterCreatePoolHook(address, address, address) external pure { return; } function setPluginForPool(address pool, address _plugin) external { poolToPlugin[pool] = _plugin; } function setTickSpacing(address pool, int24 newTickSpacing) external { IAlgebraCustomPoolEntryPoint(entryPoint).setTickSpacing(pool, newTickSpacing); } function setPlugin(address pool, address newPluginAddress) external { IAlgebraCustomPoolEntryPoint(entryPoint).setPlugin(pool, newPluginAddress); } function setPluginConfig(address pool, uint8 newConfig) external { IAlgebraCustomPoolEntryPoint(entryPoint).setPluginConfig(pool, newConfig); } function setFee(address pool, uint16 newFee) external { IAlgebraCustomPoolEntryPoint(entryPoint).setFee(pool, newFee); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../interfaces/IPositionFollower.sol'; import '../interfaces/INonfungiblePositionManager.sol'; contract MockDummyContract { uint256 junk; function write(uint256 value) external { junk = value; } } contract MockPositionFollower is IPositionFollower { enum Failure { None, ArithmeticPanic, Assert, WithMessage, WithoutMessage, WithCustomError, OutOfGas } error someCustomError(); mapping(uint256 tokenId => Failure fail) private failForToken; bool public wasCalled; MockDummyContract _dummy; constructor() { _dummy = new MockDummyContract(); } function setFailForToken(uint256 tokenId, Failure value) external { failForToken[tokenId] = value; } function enterToFarming(address posManager, uint256 tokenId) external { INonfungiblePositionManager(posManager).switchFarmingStatus(tokenId, true); } function exitFromFarming(address posManager, uint256 tokenId) external { INonfungiblePositionManager(posManager).switchFarmingStatus(tokenId, false); } function applyLiquidityDelta(uint256 tokenId, int256) external override { Failure failureMode = failForToken[tokenId]; wasCalled = true; if (failureMode == Failure.None) return; if (failureMode == Failure.ArithmeticPanic) { uint256 zero; zero = 100 / zero; } if (failureMode == Failure.Assert) { assert(false); } if (failureMode == Failure.WithMessage) { revert('Error with message'); } if (failureMode == Failure.WithoutMessage) { revert(); } if (failureMode == Failure.WithCustomError) { revert someCustomError(); } if (failureMode == Failure.OutOfGas) { _dummy.write{gas: 5000}(100); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import './TickMath.sol'; /// @title Packed tick initialized state library /// @notice Stores a packed mapping of tick index to its initialized state and search tree /// @dev The leafs mapping uses int16 for keys since ticks are represented as int24 and there are 256 (2^8) values per word. library TickTree { int16 internal constant SECOND_LAYER_OFFSET = 3466; // ceil(-MIN_TICK / 256) /// @notice Toggles the initialized state for a given tick from false to true, or vice versa /// @param leafs The mapping of words with ticks /// @param secondLayer The mapping of words with leafs /// @param treeRoot The word with info about active subtrees /// @param tick The tick to toggle function toggleTick( mapping(int16 => uint256) storage leafs, mapping(int16 => uint256) storage secondLayer, uint32 treeRoot, int24 tick ) internal returns (uint32 newTreeRoot) { newTreeRoot = treeRoot; (bool toggledNode, int16 nodeIndex) = _toggleBitInNode(leafs, tick); // toggle in leaf if (toggledNode) { unchecked { (toggledNode, nodeIndex) = _toggleBitInNode(secondLayer, nodeIndex + SECOND_LAYER_OFFSET); } if (toggledNode) { assembly { newTreeRoot := xor(newTreeRoot, shl(nodeIndex, 1)) } } } } /// @notice Toggles a bit in a tree layer by its index /// @param treeLevel The level of tree /// @param bitIndex The end-to-end index of a bit in a layer of tree /// @return toggledNode Toggled whole node or not /// @return nodeIndex Number of corresponding node function _toggleBitInNode(mapping(int16 => uint256) storage treeLevel, int24 bitIndex) private returns (bool toggledNode, int16 nodeIndex) { assembly { nodeIndex := sar(8, bitIndex) } uint256 node = treeLevel[nodeIndex]; assembly { toggledNode := iszero(node) node := xor(node, shl(and(bitIndex, 0xFF), 1)) toggledNode := xor(toggledNode, iszero(node)) } treeLevel[nodeIndex] = node; } /// @notice Returns the next initialized tick in tree to the right (gte) of the given tick or `MAX_TICK` /// @param leafs The words with ticks /// @param secondLayer The words with info about active leafs /// @param treeRoot The word with info about active subtrees /// @param tick The starting tick /// @return nextTick The next initialized tick or `MAX_TICK` function getNextTick( mapping(int16 => uint256) storage leafs, mapping(int16 => uint256) storage secondLayer, uint32 treeRoot, int24 tick ) internal view returns (int24 nextTick) { unchecked { tick++; // start searching from the next tick int16 nodeIndex; assembly { // index in treeRoot nodeIndex := shr(8, add(sar(8, tick), SECOND_LAYER_OFFSET)) } bool initialized; // if subtree has active ticks if (treeRoot & (1 << uint16(nodeIndex)) != 0) { // try to find initialized tick in the corresponding leaf of the tree (nodeIndex, nextTick, initialized) = _nextActiveBitInSameNode(leafs, tick); if (initialized) return nextTick; // try to find next initialized leaf in the tree (nodeIndex, nextTick, initialized) = _nextActiveBitInSameNode(secondLayer, nodeIndex + SECOND_LAYER_OFFSET + 1); } if (!initialized) { // try to find which subtree has an active leaf // nodeIndex is now the index of the second level node (nextTick, initialized) = _nextActiveBitInWord(treeRoot, ++nodeIndex); if (!initialized) return TickMath.MAX_TICK; nextTick = _firstActiveBitInNode(secondLayer, nextTick); // we found a second level node that has a leaf with an active tick } nextTick = _firstActiveBitInNode(leafs, nextTick - SECOND_LAYER_OFFSET); } } /// @notice Returns the index of the next active bit in the same tree node /// @param treeLevel The level of search tree /// @param bitIndex The starting bit index /// @return nodeIndex The index of corresponding node /// @return nextBitIndex The index of next active bit or last bit in node /// @return initialized Is nextBitIndex initialized or not function _nextActiveBitInSameNode( mapping(int16 => uint256) storage treeLevel, int24 bitIndex ) internal view returns (int16 nodeIndex, int24 nextBitIndex, bool initialized) { assembly { nodeIndex := sar(8, bitIndex) } (nextBitIndex, initialized) = _nextActiveBitInWord(treeLevel[nodeIndex], bitIndex); } /// @notice Returns first active bit in given node /// @param treeLevel The level of search tree /// @param nodeIndex The index of corresponding node in the level of tree /// @return bitIndex Number of next active bit or last bit in node function _firstActiveBitInNode(mapping(int16 => uint256) storage treeLevel, int24 nodeIndex) internal view returns (int24 bitIndex) { assembly { bitIndex := shl(8, nodeIndex) } (bitIndex, ) = _nextActiveBitInWord(treeLevel[int16(nodeIndex)], bitIndex); } /// @notice Returns the next initialized bit contained in the word that is to the right or at (gte) of the given bit /// @param word The word in which to compute the next initialized bit /// @param bitIndex The end-to-end index of a bit in a layer of tree /// @return nextBitIndex The next initialized or uninitialized bit up to 256 bits away from the current bit /// @return initialized Whether the next bit is initialized, as the function only searches within up to 256 bits function _nextActiveBitInWord(uint256 word, int24 bitIndex) internal pure returns (int24 nextBitIndex, bool initialized) { uint256 bitIndexInWord; assembly { bitIndexInWord := and(bitIndex, 0xFF) } unchecked { uint256 _row = word >> bitIndexInWord; // all the 1s at or to the left of the bitIndexInWord if (_row == 0) { nextBitIndex = bitIndex | 255; } else { nextBitIndex = bitIndex + int24(uint24(getSingleSignificantBit((0 - _row) & _row))); // least significant bit initialized = true; } } } /// @notice get position of single 1-bit /// @dev it is assumed that word contains exactly one 1-bit, otherwise the result will be incorrect /// @param word The word containing only one 1-bit function getSingleSignificantBit(uint256 word) internal pure returns (uint8 singleBitPos) { assembly { singleBitPos := iszero(and(word, 0x5555555555555555555555555555555555555555555555555555555555555555)) singleBitPos := or(singleBitPos, shl(7, iszero(and(word, 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)))) singleBitPos := or(singleBitPos, shl(6, iszero(and(word, 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF)))) singleBitPos := or(singleBitPos, shl(5, iszero(and(word, 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF)))) singleBitPos := or(singleBitPos, shl(4, iszero(and(word, 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF)))) singleBitPos := or(singleBitPos, shl(3, iszero(and(word, 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF)))) singleBitPos := or(singleBitPos, shl(2, iszero(and(word, 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F)))) singleBitPos := or(singleBitPos, shl(1, iszero(and(word, 0x3333333333333333333333333333333333333333333333333333333333333333)))) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4; import './pool/IAlgebraPoolImmutables.sol'; import './pool/IAlgebraPoolState.sol'; import './pool/IAlgebraPoolActions.sol'; import './pool/IAlgebraPoolPermissionedActions.sol'; import './pool/IAlgebraPoolEvents.sol'; import './pool/IAlgebraPoolErrors.sol'; /// @title The interface for a Algebra Pool /// @dev The pool interface is broken up into many smaller pieces. /// This interface includes custom error definitions and cannot be used in older versions of Solidity. /// For older versions of Solidity use #IAlgebraPoolLegacy /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPool is IAlgebraPoolImmutables, IAlgebraPoolState, IAlgebraPoolActions, IAlgebraPoolPermissionedActions, IAlgebraPoolEvents, IAlgebraPoolErrors { // used only for combining interfaces }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissioned pool actions /// @notice Contains pool methods that may only be called by permissioned addresses /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolPermissionedActions { /// @notice Set the community's % share of the fees. Only factory owner or POOLS_ADMINISTRATOR_ROLE role /// @param newCommunityFee The new community fee percent in thousandths (1e-3) function setCommunityFee(uint16 newCommunityFee) external; /// @notice Set the new tick spacing values. Only factory owner or POOLS_ADMINISTRATOR_ROLE role /// @param newTickSpacing The new tick spacing value function setTickSpacing(int24 newTickSpacing) external; /// @notice Set the new plugin address. Only factory owner or POOLS_ADMINISTRATOR_ROLE role /// @param newPluginAddress The new plugin address function setPlugin(address newPluginAddress) external; /// @notice Set new plugin config. Only factory owner or POOLS_ADMINISTRATOR_ROLE role /// @param newConfig In the new configuration of the plugin, /// each bit of which is responsible for a particular hook. function setPluginConfig(uint8 newConfig) external; /// @notice Set new community fee vault address. Only factory owner or POOLS_ADMINISTRATOR_ROLE role /// @dev Community fee vault receives collected community fees. /// **accumulated but not yet sent to the vault community fees once will be sent to the `newCommunityVault` address** /// @param newCommunityVault The address of new community fee vault function setCommunityVault(address newCommunityVault) external; /// @notice Set new pool fee. Can be called by owner if dynamic fee is disabled. /// Called by the plugin if dynamic fee is enabled /// @param newFee The new fee value function setFee(uint16 newFee) external; /// @notice Forces balances to match reserves. Excessive tokens will be distributed between active LPs /// @dev Only plugin can call this function function sync() external; /// @notice Forces balances to match reserves. Excessive tokens will be sent to msg.sender /// @dev Only plugin can call this function function skim() external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title The Algebra plugin interface /// @dev The plugin will be called by the pool using hook methods depending on the current pool settings interface IAlgebraPlugin { /// @notice Returns plugin config /// @return config Each bit of the config is responsible for enabling/disabling the hooks. /// The last bit indicates whether the plugin contains dynamic fees logic function defaultPluginConfig() external view returns (uint8); /// @notice Handle plugin fee transfer on plugin contract /// @param pluginFee0 Fee0 amount transferred to plugin /// @param pluginFee1 Fee1 amount transferred to plugin /// @return bytes4 The function selector function handlePluginFee(uint256 pluginFee0, uint256 pluginFee1) external returns (bytes4); /// @notice The hook called before the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @return bytes4 The function selector for the hook function beforeInitialize(address sender, uint160 sqrtPriceX96) external returns (bytes4); /// @notice The hook called after the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @param tick The current tick after the state of a pool is initialized /// @return bytes4 The function selector for the hook function afterInitialize(address sender, uint160 sqrtPriceX96, int24 tick) external returns (bytes4); /// @notice The hook called before a position is modified /// @param sender The initial msg.sender for the modify position call /// @param recipient Address to which the liquidity will be assigned in case of a mint or /// to which tokens will be sent in case of a burn /// @param bottomTick The lower tick of the position /// @param topTick The upper tick of the position /// @param desiredLiquidityDelta The desired amount of liquidity to mint/burn /// @param data Data that passed through the callback /// @return selector The function selector for the hook function beforeModifyPosition( address sender, address recipient, int24 bottomTick, int24 topTick, int128 desiredLiquidityDelta, bytes calldata data ) external returns (bytes4 selector, uint24 pluginFee); /// @notice The hook called after a position is modified /// @param sender The initial msg.sender for the modify position call /// @param recipient Address to which the liquidity will be assigned in case of a mint or /// to which tokens will be sent in case of a burn /// @param bottomTick The lower tick of the position /// @param topTick The upper tick of the position /// @param desiredLiquidityDelta The desired amount of liquidity to mint/burn /// @param amount0 The amount of token0 sent to the recipient or was paid to mint /// @param amount1 The amount of token0 sent to the recipient or was paid to mint /// @param data Data that passed through the callback /// @return bytes4 The function selector for the hook function afterModifyPosition( address sender, address recipient, int24 bottomTick, int24 topTick, int128 desiredLiquidityDelta, uint256 amount0, uint256 amount1, bytes calldata data ) external returns (bytes4); /// @notice The hook called before a swap /// @param sender The initial msg.sender for the swap call /// @param recipient The address to receive the output of the swap /// @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 /// @param amountRequired The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) /// @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param withPaymentInAdvance The flag indicating whether the `swapWithPaymentInAdvance` method was called /// @param data Data that passed through the callback /// @return selector The function selector for the hook function beforeSwap( address sender, address recipient, bool zeroToOne, int256 amountRequired, uint160 limitSqrtPrice, bool withPaymentInAdvance, bytes calldata data ) external returns (bytes4 selector, uint24 feeOverride, uint24 pluginFee); /// @notice The hook called after a swap /// @param sender The initial msg.sender for the swap call /// @param recipient The address to receive the output of the swap /// @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 /// @param amountRequired The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) /// @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive /// @param amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive /// @param data Data that passed through the callback /// @return bytes4 The function selector for the hook function afterSwap( address sender, address recipient, bool zeroToOne, int256 amountRequired, uint160 limitSqrtPrice, int256 amount0, int256 amount1, bytes calldata data ) external returns (bytes4); /// @notice The hook called before flash /// @param sender The initial msg.sender for the flash call /// @param recipient The address which will receive the token0 and token1 amounts /// @param amount0 The amount of token0 being requested for flash /// @param amount1 The amount of token1 being requested for flash /// @param data Data that passed through the callback /// @return bytes4 The function selector for the hook function beforeFlash(address sender, address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external returns (bytes4); /// @notice The hook called after flash /// @param sender The initial msg.sender for the flash call /// @param recipient The address which will receive the token0 and token1 amounts /// @param amount0 The amount of token0 being requested for flash /// @param amount1 The amount of token1 being requested for flash /// @param paid0 The amount of token0 being paid for flash /// @param paid1 The amount of token1 being paid for flash /// @param data Data that passed through the callback /// @return bytes4 The function selector for the hook function afterFlash( address sender, address recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; /// @title Function for getting block timestamp /// @dev Base contract that is overridden for tests abstract contract BlockTimestamp { /// @dev Method that exists purely to be overridden for tests /// @return The current block timestamp function _blockTimestamp() internal view virtual returns (uint256) { return block.timestamp; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=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. abstract contract SelfPermit is ISelfPermit { /// @inheritdoc ISelfPermit function selfPermit( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public payable override { IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s); } /// @inheritdoc ISelfPermit function selfPermitIfNecessary( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable override { if (_getAllowance(token) < value) selfPermit(token, value, deadline, v, r, s); } /// @inheritdoc ISelfPermit function selfPermitAllowed( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) public payable override { IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s); } /// @inheritdoc ISelfPermit function selfPermitAllowedIfNecessary( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external payable override { if (_getAllowance(token) < type(uint256).max) selfPermitAllowed(token, nonce, expiry, v, r, s); } function _getAllowance(address token) private view returns (uint256) { return IERC20(token).allowance(msg.sender, address(this)); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import '@cryptoalgebra/integral-core/contracts/libraries/FullMath.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/Constants.sol'; /// @title Liquidity amount functions /// @notice Provides functions for computing liquidity amounts from token amounts and prices /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library LiquidityAmounts { /// @notice Downcasts uint256 to uint128 /// @param x The uint258 to be downcasted /// @return y The passed value, downcasted to uint128 function toUint128(uint256 x) private pure returns (uint128 y) { require((y = uint128(x)) == x); } /// @notice Computes the amount of liquidity received for a given amount of token0 and price range /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower)) /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param amount0 The amount0 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount0( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, Constants.Q96); unchecked { return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96)); } } /// @notice Computes the amount of liquidity received for a given amount of token1 and price range /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)). /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param amount1 The amount1 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount1( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); unchecked { return toUint128(FullMath.mulDiv(amount1, Constants.Q96, sqrtRatioBX96 - sqrtRatioAX96)); } } /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current /// pool prices and the prices at the tick boundaries /// @param sqrtRatioX96 A sqrt price representing the current pool prices /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param amount0 The amount of token0 being sent in /// @param amount1 The amount of token1 being sent in /// @return liquidity The maximum amount of liquidity received function getLiquidityForAmounts( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0, uint256 amount1 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); if (sqrtRatioX96 <= sqrtRatioAX96) { liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0); } else if (sqrtRatioX96 < sqrtRatioBX96) { uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0); uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1); liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1; } else { liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1); } } /// @notice Computes the amount of token0 for a given amount of liquidity and a price range /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param liquidity The liquidity being valued /// @return amount0 The amount of token0 function getAmount0ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount0) { unchecked { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return FullMath.mulDiv( uint256(liquidity) << Constants.RESOLUTION, sqrtRatioBX96 - sqrtRatioAX96, sqrtRatioBX96 ) / sqrtRatioAX96; } } /// @notice Computes the amount of token1 for a given amount of liquidity and a price range /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param liquidity The liquidity being valued /// @return amount1 The amount of token1 function getAmount1ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount1) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); unchecked { return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, Constants.Q96); } } /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current /// pool prices and the prices at the tick boundaries /// @param sqrtRatioX96 A sqrt price representing the current pool prices /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary /// @param liquidity The liquidity being valued /// @return amount0 The amount of token0 /// @return amount1 The amount of token1 function getAmountsForLiquidity( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount0, uint256 amount1) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); if (sqrtRatioX96 <= sqrtRatioAX96) { amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity); } else if (sqrtRatioX96 < sqrtRatioBX96) { amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity); amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity); } else { amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSA.sol"; import "../ShortStrings.sol"; import "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; pragma abicoder v2; import './plugin/IAlgebraPluginFactory.sol'; import './vault/IAlgebraVaultFactory.sol'; /// @title The interface for the Algebra Factory /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraFactory { /// @notice Emitted when a process of ownership renounce is started /// @param timestamp The timestamp of event /// @param finishTimestamp The timestamp when ownership renounce will be possible to finish event RenounceOwnershipStart(uint256 timestamp, uint256 finishTimestamp); /// @notice Emitted when a process of ownership renounce cancelled /// @param timestamp The timestamp of event event RenounceOwnershipStop(uint256 timestamp); /// @notice Emitted when a process of ownership renounce finished /// @param timestamp The timestamp of ownership renouncement event RenounceOwnershipFinish(uint256 timestamp); /// @notice Emitted when a pool is created /// @param token0 The first token of the pool by address sort order /// @param token1 The second token of the pool by address sort order /// @param pool The address of the created pool event Pool(address indexed token0, address indexed token1, address pool); /// @notice Emitted when a pool is created /// @param deployer The corresponding custom deployer contract /// @param token0 The first token of the pool by address sort order /// @param token1 The second token of the pool by address sort order /// @param pool The address of the created pool event CustomPool(address indexed deployer, address indexed token0, address indexed token1, address pool); /// @notice Emitted when the default community fee is changed /// @param newDefaultCommunityFee The new default community fee value event DefaultCommunityFee(uint16 newDefaultCommunityFee); /// @notice Emitted when the default tickspacing is changed /// @param newDefaultTickspacing The new default tickspacing value event DefaultTickspacing(int24 newDefaultTickspacing); /// @notice Emitted when the default fee is changed /// @param newDefaultFee The new default fee value event DefaultFee(uint16 newDefaultFee); /// @notice Emitted when the defaultPluginFactory address is changed /// @param defaultPluginFactoryAddress The new defaultPluginFactory address event DefaultPluginFactory(address defaultPluginFactoryAddress); /// @notice Emitted when the vaultFactory address is changed /// @param newVaultFactory The new vaultFactory address event VaultFactory(address newVaultFactory); /// @notice role that can change communityFee and tickspacing in pools /// @return The hash corresponding to this role function POOLS_ADMINISTRATOR_ROLE() external view returns (bytes32); /// @notice role that can call `createCustomPool` function /// @return The hash corresponding to this role function CUSTOM_POOL_DEPLOYER() external view returns (bytes32); /// @notice Returns `true` if `account` has been granted `role` or `account` is owner. /// @param role The hash corresponding to the role /// @param account The address for which the role is checked /// @return bool Whether the address has this role or the owner role or not function hasRoleOrOwner(bytes32 role, address account) external view returns (bool); /// @notice Returns the current owner of the factory /// @dev Can be changed by the current owner via transferOwnership(address newOwner) /// @return The address of the factory owner function owner() external view returns (address); /// @notice Returns the current poolDeployerAddress /// @return The address of the poolDeployer function poolDeployer() external view returns (address); /// @notice Returns the default community fee /// @return Fee which will be set at the creation of the pool function defaultCommunityFee() external view returns (uint16); /// @notice Returns the default fee /// @return Fee which will be set at the creation of the pool function defaultFee() external view returns (uint16); /// @notice Returns the default tickspacing /// @return Tickspacing which will be set at the creation of the pool function defaultTickspacing() external view returns (int24); /// @notice Return the current pluginFactory address /// @dev This contract is used to automatically set a plugin address in new liquidity pools /// @return Algebra plugin factory function defaultPluginFactory() external view returns (IAlgebraPluginFactory); /// @notice Return the current vaultFactory address /// @dev This contract is used to automatically set a vault address in new liquidity pools /// @return Algebra vault factory function vaultFactory() external view returns (IAlgebraVaultFactory); /// @notice Returns the default communityFee, tickspacing, fee and communityFeeVault for pool /// @return communityFee which will be set at the creation of the pool /// @return tickSpacing which will be set at the creation of the pool /// @return fee which will be set at the creation of the pool function defaultConfigurationForPool() external view returns (uint16 communityFee, int24 tickSpacing, uint16 fee); /// @notice Deterministically computes the pool address given the token0 and token1 /// @dev The method does not check if such a pool has been created /// @param token0 first token /// @param token1 second token /// @return pool The contract address of the Algebra pool function computePoolAddress(address token0, address token1) external view returns (address pool); /// @notice Deterministically computes the custom pool address given the customDeployer, token0 and token1 /// @dev The method does not check if such a pool has been created /// @param customDeployer the address of custom plugin deployer /// @param token0 first token /// @param token1 second token /// @return customPool The contract address of the Algebra pool function computeCustomPoolAddress(address customDeployer, address token0, address token1) external view returns (address customPool); /// @notice Returns the pool address for a given pair of tokens, or address 0 if it does not exist /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @return pool The pool address function poolByPair(address tokenA, address tokenB) external view returns (address pool); /// @notice Returns the custom pool address for a customDeployer and a given pair of tokens, or address 0 if it does not exist /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order /// @param customDeployer The address of custom plugin deployer /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @return customPool The pool address function customPoolByPair(address customDeployer, address tokenA, address tokenB) external view returns (address customPool); /// @notice returns keccak256 of AlgebraPool init bytecode. /// @dev the hash value changes with any change in the pool bytecode /// @return Keccak256 hash of AlgebraPool contract init bytecode function POOL_INIT_CODE_HASH() external view returns (bytes32); /// @return timestamp The timestamp of the beginning of the renounceOwnership process function renounceOwnershipStartTimestamp() external view returns (uint256 timestamp); /// @notice Creates a pool for the given two tokens /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param data Data for plugin creation /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. /// The call will revert if the pool already exists or the token arguments are invalid. /// @return pool The address of the newly created pool function createPool(address tokenA, address tokenB, bytes calldata data) external returns (address pool); /// @notice Creates a custom pool for the given two tokens using `deployer` contract /// @param deployer The address of plugin deployer, also used for custom pool address calculation /// @param creator The initiator of custom pool creation /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param data The additional data bytes /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. /// The call will revert if the pool already exists or the token arguments are invalid. /// @return customPool The address of the newly created custom pool function createCustomPool( address deployer, address creator, address tokenA, address tokenB, bytes calldata data ) external returns (address customPool); /// @dev updates default community fee for new pools /// @param newDefaultCommunityFee The new community fee, _must_ be <= MAX_COMMUNITY_FEE function setDefaultCommunityFee(uint16 newDefaultCommunityFee) external; /// @dev updates default fee for new pools /// @param newDefaultFee The new fee, _must_ be <= MAX_DEFAULT_FEE function setDefaultFee(uint16 newDefaultFee) external; /// @dev updates default tickspacing for new pools /// @param newDefaultTickspacing The new tickspacing, _must_ be <= MAX_TICK_SPACING and >= MIN_TICK_SPACING function setDefaultTickspacing(int24 newDefaultTickspacing) external; /// @dev updates pluginFactory address /// @param newDefaultPluginFactory address of new plugin factory function setDefaultPluginFactory(address newDefaultPluginFactory) external; /// @dev updates vaultFactory address /// @param newVaultFactory address of new vault factory function setVaultFactory(address newVaultFactory) external; /// @notice Starts process of renounceOwnership. After that, a certain period /// of time must pass before the ownership renounce can be completed. function startRenounceOwnership() external; /// @notice Stops process of renounceOwnership and removes timer. function stopRenounceOwnership() external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4; /// @title Errors emitted by a pool /// @notice Contains custom errors emitted by the pool /// @dev Custom errors are separated from the common pool interface for compatibility with older versions of Solidity interface IAlgebraPoolErrors { // #### pool errors #### /// @notice Emitted by the reentrancy guard error locked(); /// @notice Emitted if arithmetic error occurred error arithmeticError(); /// @notice Emitted if an attempt is made to initialize the pool twice error alreadyInitialized(); /// @notice Emitted if an attempt is made to mint or swap in uninitialized pool error notInitialized(); /// @notice Emitted if 0 is passed as amountRequired to swap function error zeroAmountRequired(); /// @notice Emitted if invalid amount is passed as amountRequired to swap function error invalidAmountRequired(); /// @notice Emitted if plugin fee param greater than fee/override fee error incorrectPluginFee(); /// @notice Emitted if the pool received fewer tokens than it should have error insufficientInputAmount(); /// @notice Emitted if there was an attempt to mint zero liquidity error zeroLiquidityDesired(); /// @notice Emitted if actual amount of liquidity is zero (due to insufficient amount of tokens received) error zeroLiquidityActual(); /// @notice Emitted if the pool received fewer tokens0 after flash than it should have error flashInsufficientPaid0(); /// @notice Emitted if the pool received fewer tokens1 after flash than it should have error flashInsufficientPaid1(); /// @notice Emitted if limitSqrtPrice param is incorrect error invalidLimitSqrtPrice(); /// @notice Tick must be divisible by tickspacing error tickIsNotSpaced(); /// @notice Emitted if a method is called that is accessible only to the factory owner or dedicated role error notAllowed(); /// @notice Emitted if new tick spacing exceeds max allowed value error invalidNewTickSpacing(); /// @notice Emitted if new community fee exceeds max allowed value error invalidNewCommunityFee(); /// @notice Emitted if an attempt is made to manually change the fee value, but dynamic fee is enabled error dynamicFeeActive(); /// @notice Emitted if an attempt is made by plugin to change the fee value, but dynamic fee is disabled error dynamicFeeDisabled(); /// @notice Emitted if an attempt is made to change the plugin configuration, but the plugin is not connected error pluginIsNotConnected(); /// @notice Emitted if a plugin returns invalid selector after hook call /// @param expectedSelector The expected selector error invalidHookResponse(bytes4 expectedSelector); // #### LiquidityMath errors #### /// @notice Emitted if liquidity underflows error liquiditySub(); /// @notice Emitted if liquidity overflows error liquidityAdd(); // #### TickManagement errors #### /// @notice Emitted if the topTick param not greater then the bottomTick param error topTickLowerOrEqBottomTick(); /// @notice Emitted if the bottomTick param is lower than min allowed value error bottomTickLowerThanMIN(); /// @notice Emitted if the topTick param is greater than max allowed value error topTickAboveMAX(); /// @notice Emitted if the liquidity value associated with the tick exceeds MAX_LIQUIDITY_PER_TICK error liquidityOverflow(); /// @notice Emitted if an attempt is made to interact with an uninitialized tick error tickIsNotInitialized(); /// @notice Emitted if there is an attempt to insert a new tick into the list of ticks with incorrect indexes of the previous and next ticks error tickInvalidLinks(); // #### SafeTransfer errors #### /// @notice Emitted if token transfer failed internally error transferFailed(); // #### TickMath errors #### /// @notice Emitted if tick is greater than the maximum or less than the minimum allowed value error tickOutOfRange(); /// @notice Emitted if price is greater than the maximum or less than the minimum allowed value error priceOutOfRange(); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/callback/IAlgebraMintCallback.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '../libraries/PoolAddress.sol'; import '../libraries/CallbackValidation.sol'; import '../libraries/LiquidityAmounts.sol'; import '../libraries/PoolInteraction.sol'; import './PeripheryPayments.sol'; import './PeripheryImmutableState.sol'; /// @title Liquidity management functions /// @notice Internal functions for safely managing liquidity in Algebra /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract LiquidityManagement is IAlgebraMintCallback, PeripheryImmutableState, PeripheryPayments { using PoolInteraction for IAlgebraPool; struct MintCallbackData { PoolAddress.PoolKey poolKey; address payer; } /// @inheritdoc IAlgebraMintCallback function algebraMintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external override { MintCallbackData memory decoded = abi.decode(data, (MintCallbackData)); CallbackValidation.verifyCallback(poolDeployer, decoded.poolKey); if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed); if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed); } struct AddLiquidityParams { address token0; address token1; address deployer; address recipient; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; } /// @notice Add liquidity to an initialized pool function addLiquidity( AddLiquidityParams memory params ) internal returns (uint128 liquidity, uint128 actualLiquidity, uint256 amount0, uint256 amount1, IAlgebraPool pool) { PoolAddress.PoolKey memory poolKey = PoolAddress.PoolKey({ deployer: params.deployer, token0: params.token0, token1: params.token1 }); pool = IAlgebraPool(PoolAddress.computeAddress(poolDeployer, poolKey)); // compute the liquidity amount { uint160 sqrtPriceX96 = pool._getSqrtPrice(); uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower); uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper); liquidity = LiquidityAmounts.getLiquidityForAmounts( sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, params.amount0Desired, params.amount1Desired ); } (amount0, amount1, actualLiquidity) = pool.mint( msg.sender, params.recipient, params.tickLower, params.tickUpper, liquidity, abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender})) ); require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check'); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IAlgebraPoolActions#mint /// @notice Any contract that calls IAlgebraPoolActions#mint 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 IAlgebraMintCallback { /// @notice Called to `msg.sender` after minting liquidity to a position from IAlgebraPool#mint. /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity. /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity /// @param data Any data passed through by the caller via the IAlgebraPoolActions#mint call function algebraMintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.0; import "./IERC20Permit.sol"; import "../ERC20.sol"; import "../../../utils/cryptography/ECDSA.sol"; import "../../../utils/cryptography/EIP712.sol"; import "../../../utils/Counters.sol"; /** * @dev Implementation 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. * * _Available since v3.4._ */ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { using Counters for Counters.Counter; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. * However, to ensure consistency with the upgradeable transpiler, we will continue * to reserve a slot. * @custom:oz-renamed-from _PERMIT_TYPEHASH */ // solhint-disable-next-line var-name-mixedcase bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ constructor(string memory name) EIP712(name, "1") {} /** * @dev See {IERC20Permit-permit}. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _approve(owner, spender, value); } /** * @dev See {IERC20Permit-nonces}. */ function nonces(address owner) public view virtual override returns (uint256) { return _nonces[owner].current(); } /** * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @dev "Consume a nonce": return the current value and increment. * * _Available since v4.1._ */ function _useNonce(address owner) internal virtual returns (uint256 current) { Counters.Counter storage nonce = _nonces[owner]; current = nonce.current(); nonce.increment(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; /// @title ERC721 with permit /// @notice Extension to ERC721 that includes a permit function for signature based approvals interface IERC721Permit is IERC721 { /// @notice The permit typehash used in the permit signature /// @return The typehash for the permit function PERMIT_TYPEHASH() external pure returns (bytes32); /// @notice The domain separator used in the permit signature /// @return The domain separator used in encoding of permit signature function DOMAIN_SEPARATOR() external view returns (bytes32); /// @notice Approve of a specific token ID for spending by spender via signature /// @param spender The account that is being approved /// @param tokenId The ID of the token that is being approved for spending /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @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` function permit( address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Contract tracking liquidity position /// @notice Using these methods farmingCenter receives information about changes in the positions interface IPositionFollower { /// @notice Report a change of liquidity in position /// @param tokenId The ID of the token for which liquidity is being added /// @param liquidityDelta The amount of added liquidity function applyLiquidityDelta(uint256 tokenId, int256 liquidityDelta) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@cryptoalgebra/integral-core/contracts/interfaces/callback/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 ISwapRouter is IAlgebraSwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; address deployer; 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; address deployer; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 limitSqrtPrice; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @dev If native token is used as input, this function should be accompanied by a `refundNativeToken` in multicall to avoid potential loss of native tokens /// @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) /// @dev If native token is used as input, this function should be accompanied by a `refundNativeToken` in multicall to avoid potential loss of native tokens /// @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 swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingleSupportingFeeOnTransferTokens( ExactInputSingleParams calldata params ) external payable returns (uint256 amountOut); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import './PoolAddress.sol'; /// @notice Provides validation for callbacks from Algebra Pools /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library CallbackValidation { /// @notice Returns the address of a valid Algebra Pool /// @param poolDeployer The contract address of the Algebra pool deployer /// @param deployer The custom pool deployer address /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @return pool The Algebra pool contract address function verifyCallback( address poolDeployer, address deployer, address tokenA, address tokenB ) internal view returns (IAlgebraPool pool) { return verifyCallback(poolDeployer, PoolAddress.getPoolKey(deployer, tokenA, tokenB)); } /// @notice Returns the address of a valid Algebra Pool /// @param poolDeployer The contract address of the Algebra pool deployer /// @param poolKey The identifying key of the ALgebra pool /// @return pool The Algebra pool contract address function verifyCallback( address poolDeployer, PoolAddress.PoolKey memory poolKey ) internal view returns (IAlgebraPool pool) { pool = IAlgebraPool(PoolAddress.computeAddress(poolDeployer, poolKey)); require(msg.sender == address(pool), 'Invalid caller of callback'); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (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. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata 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. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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. */ function transferFrom(address from, 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. */ function approve(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. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import './PeripheryPayments.sol'; import '../interfaces/IPeripheryPaymentsWithFee.sol'; import '../interfaces/external/IWNativeToken.sol'; import '../libraries/TransferHelper.sol'; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PeripheryPaymentsWithFee is PeripheryPayments, IPeripheryPaymentsWithFee { /// @inheritdoc IPeripheryPaymentsWithFee function unwrapWNativeTokenWithFee( uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient ) public payable override { require(feeBips > 0 && feeBips <= 100); uint256 balanceWNativeToken = IWNativeToken(WNativeToken).balanceOf(address(this)); require(balanceWNativeToken >= amountMinimum, 'Insufficient WNativeToken'); if (balanceWNativeToken > 0) { IWNativeToken(WNativeToken).withdraw(balanceWNativeToken); uint256 feeAmount = (balanceWNativeToken * feeBips) / 10_000; if (feeAmount > 0) TransferHelper.safeTransferNative(feeRecipient, feeAmount); TransferHelper.safeTransferNative(recipient, balanceWNativeToken - feeAmount); } } /// @inheritdoc IPeripheryPaymentsWithFee function sweepTokenWithFee( address token, uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient ) public payable override { require(feeBips > 0 && feeBips <= 100); uint256 balanceToken = IERC20(token).balanceOf(address(this)); require(balanceToken >= amountMinimum, 'Insufficient token'); if (balanceToken > 0) { uint256 feeAmount = (balanceToken * feeBips) / 10_000; if (feeAmount > 0) TransferHelper.safeTransfer(token, feeRecipient, feeAmount); TransferHelper.safeTransfer(token, recipient, balanceToken - feeAmount); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; pragma abicoder v2; import '../SwapRouter.sol'; contract MockTimeSwapRouter is SwapRouter { uint256 time; constructor( address _factory, address _WNativeToken, address _poolDeployer ) SwapRouter(_factory, _WNativeToken, _poolDeployer) {} function _blockTimestamp() internal view override returns (uint256) { return time; } function setTime(uint256 _time) external { time = _time; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Tick Lens /// @notice Provides functions for fetching chunks of tick data for a pool /// @dev This avoids the waterfall of fetching the tick bitmap, parsing the bitmap to know which ticks to fetch, and /// then sending additional multicalls to fetch the tick data /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface ITickLens { struct PopulatedTick { int24 tick; int128 liquidityNet; uint128 liquidityGross; } /// @notice Get all the tick data for the populated ticks from a word of the tick bitmap of a pool /// @param pool The address of the pool for which to fetch populated tick data /// @param tickTableIndex The index of the word in the tick bitmap for which to parse the bitmap and /// fetch all the populated ticks /// @return populatedTicks An array of tick data for the given word in the tick bitmap function getPopulatedTicksInWord( address pool, int16 tickTableIndex ) external view returns (PopulatedTick[] memory populatedTicks); /// @notice Get closest initialized ticks around `targetTick` /// @param pool The address of the pool for which to fetch populated tick data /// @param targetTick The tick around which the nearest ticks will be searched /// @return populatedTicks An array of two ticks: before or at `targetTick` and after `targetTick` function getClosestActiveTicks( address pool, int24 targetTick ) external view returns (PopulatedTick[2] memory populatedTicks); /// @notice Get all the tick data for the `amount` (or less) of populated ticks after `startingTick` (including `startingTick` itself) /// @param pool The address of the pool for which to fetch populated tick data /// @param startingTick The starting tick index. Must be populated tick /// @param amount The maximum amount of ticks requested /// @param upperDirection The direction of search. Will fetch 'next' ticks in direction of price increase if true /// @return populatedTicks An array of tick data for fetched ticks (`amount` or less) function getNextActiveTicks( address pool, int24 startingTick, uint256 amount, bool upperDirection ) external view returns (PopulatedTick[] memory populatedTicks); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library TransferHelper { /// @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 transferred function safeTransferFrom( address token, address from, address to, uint256 value ) internal { (bool success, bytes memory 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 transfer function safeTransfer( address token, address to, uint256 value ) internal { (bool success, bytes memory 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 spend function safeApprove( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); } /// @notice Transfers NativeToken to the recipient address /// @dev Fails with `STE` /// @param to The destination of the transfer /// @param value The value to be transferred function safeTransferNative(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'STE'); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/libraries/LowGasSafeMath.sol'; import './interfaces/external/IUniswapV2Pair.sol'; import './interfaces/external/IWNativeToken.sol'; import './interfaces/INonfungiblePositionManager.sol'; import './interfaces/IV3Migrator.sol'; import './base/PeripheryImmutableState.sol'; import './base/Multicall.sol'; import './base/SelfPermit.sol'; import './base/PoolInitializer.sol'; import './libraries/TransferHelper.sol'; /// @title Algebra Migrator /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract V3Migrator is IV3Migrator, PeripheryImmutableState, PoolInitializer, Multicall, SelfPermit { using LowGasSafeMath for uint256; address public immutable nonfungiblePositionManager; constructor( address _factory, address _WNativeToken, address _nonfungiblePositionManager, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) { nonfungiblePositionManager = _nonfungiblePositionManager; } receive() external payable { require(msg.sender == WNativeToken, 'Not WNativeToken'); } function migrate(MigrateParams calldata params) external override { require(params.percentageToMigrate > 0, 'Percentage too small'); require(params.percentageToMigrate <= 100, 'Percentage too large'); // burn v2 liquidity to this address IUniswapV2Pair(params.pair).transferFrom(msg.sender, params.pair, params.liquidityToMigrate); (uint256 amount0V2, uint256 amount1V2) = IUniswapV2Pair(params.pair).burn(address(this)); // calculate the amounts to migrate to v3 uint256 amount0V2ToMigrate = (amount0V2 * params.percentageToMigrate) / 100; uint256 amount1V2ToMigrate = (amount1V2 * params.percentageToMigrate) / 100; // approve the position manager up to the maximum token amounts TransferHelper.safeApprove(params.token0, nonfungiblePositionManager, amount0V2ToMigrate); TransferHelper.safeApprove(params.token1, nonfungiblePositionManager, amount1V2ToMigrate); // mint v3 position (, , uint256 amount0V3, uint256 amount1V3) = INonfungiblePositionManager(nonfungiblePositionManager).mint( INonfungiblePositionManager.MintParams({ token0: params.token0, token1: params.token1, deployer: params.deployer, tickLower: params.tickLower, tickUpper: params.tickUpper, amount0Desired: amount0V2ToMigrate, amount1Desired: amount1V2ToMigrate, amount0Min: params.amount0Min, amount1Min: params.amount1Min, recipient: params.recipient, deadline: params.deadline }) ); // if necessary, clear allowance and refund dust if (amount0V3 < amount0V2) { if (amount0V3 < amount0V2ToMigrate) { TransferHelper.safeApprove(params.token0, nonfungiblePositionManager, 0); } uint256 refund0 = amount0V2 - amount0V3; if (params.refundAsNative && params.token0 == WNativeToken) { IWNativeToken(WNativeToken).withdraw(refund0); TransferHelper.safeTransferNative(msg.sender, refund0); } else { TransferHelper.safeTransfer(params.token0, msg.sender, refund0); } } if (amount1V3 < amount1V2) { if (amount1V3 < amount1V2ToMigrate) { TransferHelper.safeApprove(params.token1, nonfungiblePositionManager, 0); } uint256 refund1 = amount1V2 - amount1V3; if (params.refundAsNative && params.token1 == WNativeToken) { IWNativeToken(WNativeToken).withdraw(refund1); TransferHelper.safeTransferNative(msg.sender, refund1); } else { TransferHelper.safeTransfer(params.token1, msg.sender, refund1); } } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../libraries/Path.sol'; contract PathTest { function hasMultiplePools(bytes memory path) public pure returns (bool) { return Path.hasMultiplePools(path); } function decodeFirstPool(bytes memory path) public pure returns (address tokenA, address deployer, address tokenB) { return Path.decodeFirstPool(path); } function getFirstPool(bytes memory path) public pure returns (bytes memory) { return Path.getFirstPool(path); } function skipToken(bytes memory path) public pure returns (bytes memory) { return Path.skipToken(path); } // gas funcs function getGasCostOfDecodeFirstPool(bytes memory path) public view returns (uint256) { uint256 gasBefore = gasleft(); Path.decodeFirstPool(path); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '../interfaces/IPeripheryImmutableState.sol'; /// @title Immutable state /// @notice Immutable state used by periphery contracts /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PeripheryImmutableState is IPeripheryImmutableState { /// @inheritdoc IPeripheryImmutableState address public immutable override factory; /// @inheritdoc IPeripheryImmutableState address public immutable override poolDeployer; /// @inheritdoc IPeripheryImmutableState address public immutable override WNativeToken; constructor(address _factory, address _WNativeToken, address _poolDeployer) { factory = _factory; poolDeployer = _poolDeployer; WNativeToken = _WNativeToken; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/libraries/TickTree.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickManagement.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '../../lens/TickLens.sol'; contract TickLensEchidnaTest { using TickManagement for mapping(int24 => TickManagement.Tick); address private tickLens; mapping(int24 => TickManagement.Tick) public ticks; uint32 public tickTreeRoot; // The root bitmap of search tree mapping(int16 => uint256) public tickTreeSecondLayer; // The second layer of search tree mapping(int16 => uint256) public tickTable; // leafs of search tree constructor() { tickLens = address(new TickLens()); ticks.initTickState(); } function toggleTick(int24 tick) external { tick = _boundTick(tick); tickTreeRoot = TickTree.toggleTick(tickTable, tickTreeSecondLayer, tickTreeRoot, tick); if (ticks[tick].prevTick == ticks[tick].nextTick) { int24 nextTick = TickTree.getNextTick(tickTable, tickTreeSecondLayer, tickTreeRoot, tick); int24 prevTick = ticks[nextTick].prevTick; ticks.insertTick(tick, prevTick, nextTick); } else { ticks.removeTick(tick); } } function checkNextTickAssertions(int24 targetTick) external view { targetTick = _boundTick(targetTick); TickLens.PopulatedTick[2] memory populatedTicks = TickLens(tickLens).getClosestActiveTicks( address(this), targetTick ); assert(populatedTicks[0].tick <= targetTick); assert(populatedTicks[1].tick > targetTick); int24 nextTick = TickTree.getNextTick(tickTable, tickTreeSecondLayer, tickTreeRoot, targetTick); assert(nextTick == populatedTicks[1].tick); assert(ticks[populatedTicks[0].tick].nextTick == nextTick); assert(ticks[nextTick].prevTick == populatedTicks[0].tick); } function _boundTick(int24 tick) private pure returns (int24) { if (tick >= TickMath.MAX_TICK) tick = TickMath.MAX_TICK - 1; if (tick <= TickMath.MIN_TICK) tick = TickMath.MIN_TICK + 1; return tick; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Interface for verifying contract-based account signatures /// @notice Interface that verifies provided signature for the data /// @dev Interface defined by EIP-1271 interface IERC1271 { /// @notice Returns whether the provided signature is valid for the provided data /// @dev MUST return the bytes4 magic value 0x1626ba7e when function passes. /// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5). /// MUST allow external calls. /// @param hash Hash of the data to be signed /// @param signature Signature byte array associated with _data /// @return magicValue The bytes4 magic value 0x1626ba7e function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/callback/IAlgebraSwapCallback.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/SafeCast.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; contract TestAlgebraCallee is IAlgebraSwapCallback { using SafeCast for uint256; function swapExact0For1(address pool, uint256 amount0In, address recipient, uint160 limitSqrtPrice) external { IAlgebraPool(pool).swap(recipient, true, amount0In.toInt256(), limitSqrtPrice, abi.encode(msg.sender)); } function swap0ForExact1(address pool, uint256 amount1Out, address recipient, uint160 limitSqrtPrice) external { IAlgebraPool(pool).swap(recipient, true, -amount1Out.toInt256(), limitSqrtPrice, abi.encode(msg.sender)); } function swapExact1For0(address pool, uint256 amount1In, address recipient, uint160 limitSqrtPrice) external { IAlgebraPool(pool).swap(recipient, false, amount1In.toInt256(), limitSqrtPrice, abi.encode(msg.sender)); } function swap1ForExact0(address pool, uint256 amount0Out, address recipient, uint160 limitSqrtPrice) external { IAlgebraPool(pool).swap(recipient, false, -amount0Out.toInt256(), limitSqrtPrice, abi.encode(msg.sender)); } function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external override { address sender = abi.decode(data, (address)); if (amount0Delta > 0) { IERC20(IAlgebraPool(msg.sender).token0()).transferFrom(sender, msg.sender, uint256(amount0Delta)); } else { assert(amount1Delta > 0); IERC20(IAlgebraPool(msg.sender).token1()).transferFrom(sender, msg.sender, uint256(amount1Delta)); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; import './IPeripheryPayments.sol'; /// @title Periphery Payments /// @notice Functions to ease deposits and withdrawals of NativeToken /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IPeripheryPaymentsWithFee is IPeripheryPayments { /// @notice Unwraps the contract's WNativeToken balance and sends it to recipient as NativeToken, with a percentage between /// 0 (exclusive), and 1 (inclusive) going to feeRecipient /// @dev The amountMinimum parameter prevents malicious contracts from stealing WNativeToken from users. function unwrapWNativeTokenWithFee( uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient ) external payable; /// @notice Transfers the full amount of a token held by this contract to recipient, with a percentage between /// 0 (exclusive) and 1 (inclusive) going to feeRecipient /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users function sweepTokenWithFee( address token, uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '../libraries/PoolTicksCounter.sol'; contract PoolTicksCounterTest { using PoolTicksCounter for IAlgebraPool; mapping(int16 => uint256) public tickTable; int16 public tickSpacing; function setTickTableWord(int16 index, uint256 value) external { tickTable[index] = value; } function setTickSpacing(int16 newValue) external { tickSpacing = newValue; } function countInitializedTicksCrossed( IAlgebraPool pool, int24 tickBefore, int24 tickAfter ) external view returns (uint32 initializedTicksCrossed) { return pool.countInitializedTicksCrossed(tickBefore, tickAfter); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import '../interfaces/pool/IAlgebraPoolErrors.sol'; import './TickMath.sol'; import './LiquidityMath.sol'; import './Constants.sol'; /// @title Library for managing and interacting with ticks /// @notice Contains functions for managing tick processes and relevant calculations /// @dev Ticks are organized as a doubly linked list library TickManagement { // info stored for each initialized individual tick struct Tick { uint256 liquidityTotal; // the total position liquidity that references this tick int128 liquidityDelta; // amount of net liquidity added (subtracted) when tick is crossed left-right (right-left), int24 prevTick; int24 nextTick; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 outerFeeGrowth0Token; uint256 outerFeeGrowth1Token; } function checkTickRangeValidity(int24 bottomTick, int24 topTick) internal pure { if (topTick > TickMath.MAX_TICK) revert IAlgebraPoolErrors.topTickAboveMAX(); if (topTick <= bottomTick) revert IAlgebraPoolErrors.topTickLowerOrEqBottomTick(); if (bottomTick < TickMath.MIN_TICK) revert IAlgebraPoolErrors.bottomTickLowerThanMIN(); } /// @notice Retrieves fee growth data /// @param self The mapping containing all tick information for initialized ticks /// @param bottomTick The lower tick boundary of the position /// @param topTick The upper tick boundary of the position /// @param currentTick The current tick /// @param totalFeeGrowth0Token The all-time global fee growth, per unit of liquidity, in token0 /// @param totalFeeGrowth1Token The all-time global fee growth, per unit of liquidity, in token1 /// @return innerFeeGrowth0Token The all-time fee growth in token0, per unit of liquidity, inside the position's tick boundaries /// @return innerFeeGrowth1Token The all-time fee growth in token1, per unit of liquidity, inside the position's tick boundaries function getInnerFeeGrowth( mapping(int24 => Tick) storage self, int24 bottomTick, int24 topTick, int24 currentTick, uint256 totalFeeGrowth0Token, uint256 totalFeeGrowth1Token ) internal view returns (uint256 innerFeeGrowth0Token, uint256 innerFeeGrowth1Token) { Tick storage lower = self[bottomTick]; Tick storage upper = self[topTick]; unchecked { if (currentTick < topTick) { if (currentTick >= bottomTick) { innerFeeGrowth0Token = totalFeeGrowth0Token - lower.outerFeeGrowth0Token; innerFeeGrowth1Token = totalFeeGrowth1Token - lower.outerFeeGrowth1Token; } else { innerFeeGrowth0Token = lower.outerFeeGrowth0Token; innerFeeGrowth1Token = lower.outerFeeGrowth1Token; } innerFeeGrowth0Token -= upper.outerFeeGrowth0Token; innerFeeGrowth1Token -= upper.outerFeeGrowth1Token; } else { innerFeeGrowth0Token = upper.outerFeeGrowth0Token - lower.outerFeeGrowth0Token; innerFeeGrowth1Token = upper.outerFeeGrowth1Token - lower.outerFeeGrowth1Token; } } } /// @notice Updates a tick and returns true if the tick was flipped from initialized to uninitialized, or vice versa /// @param self The mapping containing all tick information for initialized ticks /// @param tick The tick that will be updated /// @param currentTick The current tick /// @param liquidityDelta A new amount of liquidity to be added (subtracted) when tick is crossed from left to right (right to left) /// @param totalFeeGrowth0Token The all-time global fee growth, per unit of liquidity, in token0 /// @param totalFeeGrowth1Token The all-time global fee growth, per unit of liquidity, in token1 /// @param upper True for updating a position's upper tick, or false for updating a position's lower tick /// @return flipped Whether the tick was flipped from initialized to uninitialized, or vice versa function update( mapping(int24 => Tick) storage self, int24 tick, int24 currentTick, int128 liquidityDelta, uint256 totalFeeGrowth0Token, uint256 totalFeeGrowth1Token, bool upper ) internal returns (bool flipped) { Tick storage data = self[tick]; uint256 liquidityTotalBefore = data.liquidityTotal; uint256 liquidityTotalAfter = LiquidityMath.addDelta(uint128(liquidityTotalBefore), liquidityDelta); if (liquidityTotalAfter > Constants.MAX_LIQUIDITY_PER_TICK) revert IAlgebraPoolErrors.liquidityOverflow(); int128 liquidityDeltaBefore = data.liquidityDelta; // when the lower (upper) tick is crossed left to right (right to left), liquidity must be added (removed) data.liquidityDelta = upper ? int128(int256(liquidityDeltaBefore) - liquidityDelta) : int128(int256(liquidityDeltaBefore) + liquidityDelta); data.liquidityTotal = liquidityTotalAfter; flipped = (liquidityTotalAfter == 0); if (liquidityTotalBefore == 0) { flipped = !flipped; // by convention, we assume that all growth before a tick was initialized happened _below_ the tick if (tick <= currentTick) (data.outerFeeGrowth0Token, data.outerFeeGrowth1Token) = (totalFeeGrowth0Token, totalFeeGrowth1Token); } } /// @notice Transitions to next tick as needed by price movement /// @param self The mapping containing all tick information for initialized ticks /// @param tick The destination tick of the transition /// @param feeGrowth0 The all-time global fee growth, per unit of liquidity, in token0 /// @param feeGrowth1 The all-time global fee growth, per unit of liquidity, in token1 /// @return liquidityDelta The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left) /// @return prevTick The previous active tick before _tick_ /// @return nextTick The next active tick after _tick_ function cross( mapping(int24 => Tick) storage self, int24 tick, uint256 feeGrowth0, uint256 feeGrowth1 ) internal returns (int128 liquidityDelta, int24 prevTick, int24 nextTick) { Tick storage data = self[tick]; unchecked { (data.outerFeeGrowth1Token, data.outerFeeGrowth0Token) = (feeGrowth1 - data.outerFeeGrowth1Token, feeGrowth0 - data.outerFeeGrowth0Token); } return (data.liquidityDelta, data.prevTick, data.nextTick); } /// @notice Used for initial setup of ticks list /// @param self The mapping containing all tick information for initialized ticks function initTickState(mapping(int24 => Tick) storage self) internal { (self[TickMath.MIN_TICK].prevTick, self[TickMath.MIN_TICK].nextTick) = (TickMath.MIN_TICK, TickMath.MAX_TICK); (self[TickMath.MAX_TICK].prevTick, self[TickMath.MAX_TICK].nextTick) = (TickMath.MIN_TICK, TickMath.MAX_TICK); } /// @notice Removes tick from the linked list /// @param self The mapping containing all tick information for initialized ticks /// @param tick The tick that will be removed /// @return prevTick The previous active tick before _tick_ /// @return nextTick The next active tick after _tick_ function removeTick(mapping(int24 => Tick) storage self, int24 tick) internal returns (int24 prevTick, int24 nextTick) { (prevTick, nextTick) = (self[tick].prevTick, self[tick].nextTick); delete self[tick]; if (tick == TickMath.MIN_TICK || tick == TickMath.MAX_TICK) { // MIN_TICK and MAX_TICK cannot be removed from tick list (self[tick].prevTick, self[tick].nextTick) = (prevTick, nextTick); } else { if (prevTick == nextTick) revert IAlgebraPoolErrors.tickIsNotInitialized(); self[prevTick].nextTick = nextTick; self[nextTick].prevTick = prevTick; } return (prevTick, nextTick); } /// @notice Adds tick to the linked list /// @param self The mapping containing all tick information for initialized ticks /// @param tick The tick that will be inserted /// @param prevTick The previous active tick before _tick_ /// @param nextTick The next active tick after _tick_ function insertTick(mapping(int24 => Tick) storage self, int24 tick, int24 prevTick, int24 nextTick) internal { if (tick == TickMath.MIN_TICK || tick == TickMath.MAX_TICK) return; if (!(prevTick < tick && nextTick > tick)) revert IAlgebraPoolErrors.tickInvalidLinks(); (self[tick].prevTick, self[tick].nextTick) = (prevTick, nextTick); self[prevTick].nextTick = tick; self[nextTick].prevTick = tick; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/libraries/SafeCast.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/FullMath.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/callback/IAlgebraSwapCallback.sol'; import '../interfaces/IQuoter.sol'; import '../base/PeripheryImmutableState.sol'; import '../libraries/Path.sol'; import '../libraries/PoolAddress.sol'; import '../libraries/CallbackValidation.sol'; /// @title Algebra Integral 1.2.1 Quoter /// @notice Allows getting the expected amount out or amount in for a given swap without executing the swap /// @dev These functions are not gas efficient and should _not_ be called on chain. Instead, optimistically execute /// the swap and check the amounts in the callback. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract Quoter is IQuoter, IAlgebraSwapCallback, PeripheryImmutableState { using Path for bytes; using SafeCast for uint256; /// @dev Transient storage variable used to check a safety condition in exact output swaps. uint256 private amountOutCached; constructor( address _factory, address _WNativeToken, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) {} function getPool(address deployer, address tokenA, address tokenB) private view returns (IAlgebraPool) { return IAlgebraPool(PoolAddress.computeAddress(poolDeployer, PoolAddress.getPoolKey(deployer, tokenA, tokenB))); } /// @inheritdoc IAlgebraSwapCallback function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes memory path) external view override { require(amount0Delta > 0 || amount1Delta > 0, 'Zero liquidity swap'); // swaps entirely within 0-liquidity regions are not supported (address tokenIn, address deployer, address tokenOut) = path.decodeFirstPool(); CallbackValidation.verifyCallback(poolDeployer, deployer, tokenIn, tokenOut); (bool isExactInput, uint256 amountToPay, uint256 amountReceived) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta), uint256(-amount1Delta)) : (tokenOut < tokenIn, uint256(amount1Delta), uint256(-amount0Delta)); IAlgebraPool pool = getPool(deployer, tokenIn, tokenOut); (, , uint16 fee, , , ) = pool.globalState(); if (isExactInput) { assembly { let ptr := mload(0x40) mstore(ptr, amountReceived) mstore(add(ptr, 0x20), fee) revert(ptr, 64) } } else { // if the cache has been populated, ensure that the full output amount has been received if (amountOutCached != 0) require(amountReceived == amountOutCached, 'Not received full amountOut'); assembly { let ptr := mload(0x40) mstore(ptr, amountToPay) mstore(add(ptr, 0x20), fee) revert(ptr, 64) } } } /// @dev Parses a revert reason that should contain the numeric quote function parseRevertReason(bytes memory reason) private pure returns (uint256, uint16) { if (reason.length != 64) { require(reason.length > 0, 'Unexpected error'); assembly ('memory-safe') { revert(add(32, reason), mload(reason)) } } return abi.decode(reason, (uint256, uint16)); } /// @inheritdoc IQuoter function quoteExactInputSingle( address tokenIn, address tokenOut, address deployer, uint256 amountIn, uint160 limitSqrtPrice ) public override returns (uint256 amountOut, uint16 fee) { bool zeroToOne = tokenIn < tokenOut; try getPool(deployer, tokenIn, tokenOut).swap( address(this), // address(0) might cause issues with some tokens zeroToOne, amountIn.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encodePacked(tokenIn, deployer, tokenOut) ) {} catch (bytes memory reason) { (amountOut, fee) = parseRevertReason(reason); } } /// @inheritdoc IQuoter function quoteExactInput( bytes memory path, uint256 amountIn ) external override returns (uint256 amountOut, uint16[] memory fees) { fees = new uint16[](path.numPools()); uint256 i = 0; while (true) { bool hasMultiplePools = path.hasMultiplePools(); (address tokenIn, address deployer, address tokenOut) = path.decodeFirstPool(); // the outputs of prior swaps become the inputs to subsequent ones (amountIn, fees[i]) = quoteExactInputSingle(tokenIn, tokenOut, deployer, amountIn, 0); // decide whether to continue or terminate if (hasMultiplePools) { path = path.skipToken(); } else { return (amountIn, fees); } i++; } } /// @inheritdoc IQuoter function quoteExactOutputSingle( address tokenIn, address tokenOut, address deployer, uint256 amountOut, uint160 limitSqrtPrice ) public override returns (uint256 amountIn, uint16 fee) { bool zeroToOne = tokenIn < tokenOut; // if no price limit has been specified, cache the output amount for comparison in the swap callback if (limitSqrtPrice == 0) amountOutCached = amountOut; try getPool(deployer, tokenIn, tokenOut).swap( address(this), // address(0) might cause issues with some tokens zeroToOne, -amountOut.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encodePacked(tokenOut, deployer, tokenIn) ) {} catch (bytes memory reason) { if (limitSqrtPrice == 0) delete amountOutCached; // clear cache (amountIn, fee) = parseRevertReason(reason); } } /// @inheritdoc IQuoter function quoteExactOutput( bytes memory path, uint256 amountOut ) external override returns (uint256 amountIn, uint16[] memory fees) { fees = new uint16[](path.numPools()); uint256 i = 0; while (true) { bool hasMultiplePools = path.hasMultiplePools(); (address tokenOut, address deployer, address tokenIn) = path.decodeFirstPool(); // the inputs of prior swaps become the outputs of subsequent ones (amountOut, fees[i]) = quoteExactOutputSingle(tokenIn, tokenOut, deployer, amountOut, 0); // decide whether to continue or terminate if (hasMultiplePools) { path = path.skipToken(); } else { return (amountOut, fees); } i++; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Quoter Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IQuoter { /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair /// @param amountIn The amount of the first token to swap /// @return amountOut The amount of the last token that would be received function quoteExactInput( bytes memory path, uint256 amountIn ) external returns (uint256 amountOut, uint16[] memory fees); /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param tokenIn The token being swapped in /// @param tokenOut The token being swapped out /// @param amountIn The desired input amount /// @param limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received function quoteExactInputSingle( address tokenIn, address tokenOut, address deployer, uint256 amountIn, uint160 limitSqrtPrice ) external returns (uint256 amountOut, uint16 fee); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair. Path must be provided in reverse order /// @param amountOut The amount of the last token to receive /// @return amountIn The amount of first token required to be paid function quoteExactOutput( bytes memory path, uint256 amountOut ) external returns (uint256 amountIn, uint16[] memory fees); /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param tokenIn The token being swapped in /// @param tokenOut The token being swapped out /// @param amountOut The desired output amount /// @param limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` function quoteExactOutputSingle( address tokenIn, address tokenOut, address deployer, uint256 amountOut, uint160 limitSqrtPrice ) external returns (uint256 amountIn, uint16 fee); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol'; import './IPoolInitializer.sol'; import './IERC721Permit.sol'; import './IPeripheryPayments.sol'; import './IPeripheryImmutableState.sol'; /// @title Non-fungible token for positions /// @notice Wraps Algebra positions in a non-fungible token interface which allows for them to be transferred /// and authorized. /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface INonfungiblePositionManager is IPoolInitializer, IPeripheryPayments, IPeripheryImmutableState, IERC721Metadata, IERC721Enumerable, IERC721Permit { /// @notice Emitted when liquidity is increased for a position NFT /// @dev Also emitted when a token is minted /// @param tokenId The ID of the token for which liquidity was increased /// @param liquidityDesired The amount by which liquidity for the NFT position was increased /// @param actualLiquidity the actual liquidity that was added into a pool. Could differ from /// _liquidity_ when using FeeOnTransfer tokens /// @param amount0 The amount of token0 that was paid for the increase in liquidity /// @param amount1 The amount of token1 that was paid for the increase in liquidity event IncreaseLiquidity( uint256 indexed tokenId, uint128 liquidityDesired, uint128 actualLiquidity, uint256 amount0, uint256 amount1, address pool ); /// @notice Emitted when liquidity is decreased for a position NFT /// @param tokenId The ID of the token for which liquidity was decreased /// @param liquidity The amount by which liquidity for the NFT position was decreased /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); /// @notice Emitted when tokens are collected for a position NFT /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior /// @param tokenId The ID of the token for which underlying tokens were collected /// @param recipient The address of the account that received the collected tokens /// @param amount0 The amount of token0 owed to the position that was collected /// @param amount1 The amount of token1 owed to the position that was collected event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1); /// @notice Emitted if farming failed in call from NonfungiblePositionManager. /// @dev Should never be emitted /// @param tokenId The ID of corresponding token event FarmingFailed(uint256 indexed tokenId); /// @notice Returns the position information associated with a given token ID. /// @dev Throws if the token ID is not valid. /// @param tokenId The ID of the token that represents the position /// @return nonce The nonce for permits /// @return operator The address that is approved for spending /// @return token0 The address of the token0 for a specific pool /// @return token1 The address of the token1 for a specific pool /// @return deployer The address of the custom pool deployer /// @return tickLower The lower end of the tick range for the position /// @return tickUpper The higher end of the tick range for the position /// @return liquidity The liquidity of the position /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation function positions( uint256 tokenId ) external view returns ( uint88 nonce, address operator, address token0, address token1, address deployer, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); struct MintParams { address token0; address token1; address deployer; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } /// @notice Creates a new position wrapped in a NFT /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized /// a method does not exist, i.e. the pool is assumed to be initialized. /// @dev If native token is used as input, this function should be accompanied by a `refundNativeToken` in multicall to avoid potential loss of native tokens /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata /// @return tokenId The ID of the token that represents the minted position /// @return liquidity The liquidity delta amount as a result of the increase /// @return amount0 The amount of token0 /// @return amount1 The amount of token1 function mint( MintParams calldata params ) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` /// @param params tokenId The ID of the token for which liquidity is being increased, /// amount0Desired The desired amount of token0 to be spent, /// amount1Desired The desired amount of token1 to be spent, /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, /// deadline The time by which the transaction must be included to effect the change /// @dev If native token is used as input, this function should be accompanied by a `refundNativeToken` in multicall to avoid potential loss of native tokens /// @return liquidity The liquidity delta amount as a result of the increase /// @return amount0 The amount of token0 to achieve resulting liquidity /// @return amount1 The amount of token1 to achieve resulting liquidity function increaseLiquidity( IncreaseLiquidityParams calldata params ) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1); struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Decreases the amount of liquidity in a position and accounts it to the position /// @param params tokenId The ID of the token for which liquidity is being decreased, /// amount The amount by which liquidity will be decreased, /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, /// deadline The time by which the transaction must be included to effect the change /// @return amount0 The amount of token0 accounted to the position's tokens owed /// @return amount1 The amount of token1 accounted to the position's tokens owed function decreaseLiquidity( DecreaseLiquidityParams calldata params ) external payable returns (uint256 amount0, uint256 amount1); struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; } /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient /// @param params tokenId The ID of the NFT for which tokens are being collected, /// recipient The account that should receive the tokens, /// amount0Max The maximum amount of token0 to collect, /// amount1Max The maximum amount of token1 to collect /// @return amount0 The amount of fees collected in token0 /// @return amount1 The amount of fees collected in token1 function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens /// must be collected first. /// @param tokenId The ID of the token that is being burned function burn(uint256 tokenId) external payable; /// @notice Changes approval of token ID for farming. /// @param tokenId The ID of the token that is being approved / unapproved /// @param approve New status of approval /// @param farmingAddress The address of farming: used to prevent tx frontrun function approveForFarming(uint256 tokenId, bool approve, address farmingAddress) external payable; /// @notice Changes farming status of token to 'farmed' or 'not farmed' /// @dev can be called only by farmingCenter /// @param tokenId The ID of the token /// @param toActive The new status function switchFarmingStatus(uint256 tokenId, bool toActive) external; /// @notice Changes address of farmingCenter /// @dev can be called only by factory owner or NONFUNGIBLE_POSITION_MANAGER_ADMINISTRATOR_ROLE /// @param newFarmingCenter The new address of farmingCenter function setFarmingCenter(address newFarmingCenter) external; /// @notice Returns whether `spender` is allowed to manage `tokenId` /// @dev Requirement: `tokenId` must exist function isApprovedOrOwner(address spender, uint256 tokenId) external view returns (bool); /// @notice Returns the address of currently connected farming, if any /// @return The address of the farming center contract, which handles farmings logic function farmingCenter() external view returns (address); /// @notice Returns the address of farming that is approved for this token, if any function farmingApprovals(uint256 tokenId) external view returns (address); /// @notice Returns the address of farming in which this token is farmed, if any function tokenFarmedIn(uint256 tokenId) external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Immutable state /// @notice Functions that return immutable state of the router /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IPeripheryImmutableState { /// @return Returns the address of the Algebra factory function factory() external view returns (address); /// @return Returns the address of the pool Deployer function poolDeployer() external view returns (address); /// @return Returns the address of WNativeToken function WNativeToken() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0 <0.9.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library SafeCast { /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { require((z = uint160(y)) == y); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint128(uint256 y) internal pure returns (uint128 z) { require((z = uint128(y)) == y); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { require((z = int128(y)) == y); } /// @notice Cast a uint128 to a int128, revert on overflow /// @param y The uint128 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(uint128 y) internal pure returns (int128 z) { require((z = int128(y)) >= 0); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { require((z = int256(y)) >= 0); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '../base/PeripheryImmutableState.sol'; contract PeripheryImmutableStateTest is PeripheryImmutableState { constructor( address _factory, address _WNativeToken, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) {} }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0 <0.9.0; /// @title Contains common constants for Algebra contracts /// @dev Constants moved to the library, not the base contract, to further emphasize their constant nature library Constants { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 1 << 96; uint256 internal constant Q128 = 1 << 128; uint24 internal constant FEE_DENOMINATOR = 1e6; uint16 internal constant FLASH_FEE = 0.01e4; // fee for flash loan in hundredths of a bip (0.01%) uint16 internal constant INIT_DEFAULT_FEE = 0.05e4; // init default fee value in hundredths of a bip (0.05%) uint16 internal constant MAX_DEFAULT_FEE = 5e4; // max default fee value in hundredths of a bip (5%) int24 internal constant INIT_DEFAULT_TICK_SPACING = 60; int24 internal constant MAX_TICK_SPACING = 500; int24 internal constant MIN_TICK_SPACING = 1; // the frequency with which the accumulated community fees are sent to the vault uint32 internal constant FEE_TRANSFER_FREQUENCY = 8 hours; // max(uint128) / (MAX_TICK - MIN_TICK) uint128 internal constant MAX_LIQUIDITY_PER_TICK = 191757638537527648490752896198553; uint16 internal constant MAX_COMMUNITY_FEE = 1e3; // 100% uint256 internal constant COMMUNITY_FEE_DENOMINATOR = 1e3; // role that can change settings in pools bytes32 internal constant POOLS_ADMINISTRATOR_ROLE = keccak256('POOLS_ADMINISTRATOR'); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title An interface for a contract that is capable of deploying Algebra plugins /// @dev Such a factory can be used for automatic plugin creation for new pools. /// Also a factory be used as an entry point for custom (additional) pools creation interface IAlgebraPluginFactory { /// @notice Deploys new plugin contract for pool /// @param pool The address of the new pool /// @param creator The address that initiated the pool creation /// @param deployer The address of new plugin deployer contract (0 if not used) /// @param token0 First token of the pool /// @param token1 Second token of the pool /// @return New plugin address function beforeCreatePoolHook( address pool, address creator, address deployer, address token0, address token1, bytes calldata data ) external returns (address); /// @notice Called after the pool is created /// @param plugin The plugin address /// @param pool The address of the new pool /// @param deployer The address of new plugin deployer contract (0 if not used) function afterCreatePoolHook(address plugin, address pool, address deployer) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^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 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (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. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (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. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.8; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../libraries/CallbackValidation.sol'; contract TestCallbackValidation { function verifyCallback( address factory, address tokenA, address tokenB, address deployer ) external view returns (IAlgebraPool pool) { return CallbackValidation.verifyCallback(factory, tokenA, tokenB, deployer); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import '@cryptoalgebra/integral-core/contracts/interfaces/plugin/IAlgebraPluginFactory.sol'; /// @title An interface for a contract that is used to deploy and manage Algebra Integral custom pools /// @dev This contract should be called by every custom pool deployer to create new custom pools or manage existing ones. interface IAlgebraCustomPoolEntryPoint is IAlgebraPluginFactory { /// @notice Returns the address of corresponding AlgebraFactory contract /// @return factory The address of AlgebraFactory function factory() external view returns (address factory); /// @notice Using for custom pools creation /// @param deployer The address of plugin deployer, also used for custom pool address calculation /// @param creator The initiator of custom pool creation /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param data The additional data bytes function createCustomPool( address deployer, address creator, address tokenA, address tokenB, bytes calldata data ) external returns (address customPool); /// @notice Changes the tick spacing value in the Algebra Integral custom pool /// @dev Only corresponding custom pool deployer contract can call this function /// @param pool The address of the Algebra Integral custom pool /// @param newTickSpacing The new tick spacing value function setTickSpacing(address pool, int24 newTickSpacing) external; /// @notice Changes the plugin address in the Algebra Integral custom pool /// @dev Only corresponding custom pool deployer contract can call this function /// @param pool The address of the Algebra Integral custom pool /// @param newPluginAddress The new plugin address function setPlugin(address pool, address newPluginAddress) external; /// @notice Changes the plugin configuration in the Algebra Integral custom pool /// @dev Only corresponding custom pool deployer contract can call this function /// @param pool The address of the Algebra Integral custom pool /// @param newConfig The new plugin configuration bitmap function setPluginConfig(address pool, uint8 newConfig) external; /// @notice Changes the fee value in the Algebra Integral custom pool /// @dev Only corresponding custom pool deployer contract can call this function. /// Fee can be changed manually only if pool does not have "dynamic fee" configuration /// @param pool The address of the Algebra Integral custom pool /// @param newFee The new fee value function setFee(address pool, uint16 newFee) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; /// @title Periphery Payments /// @notice Functions to ease deposits and withdrawals of NativeToken /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IPeripheryPayments { /// @notice Unwraps the contract's WNativeToken balance and sends it to recipient as NativeToken. /// @dev The amountMinimum parameter prevents malicious contracts from stealing WNativeToken from users. /// @param amountMinimum The minimum amount of WNativeToken to unwrap /// @param recipient The address receiving NativeToken function unwrapWNativeToken(uint256 amountMinimum, address recipient) external payable; /// @notice Refunds any NativeToken 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 amount function refundNativeToken() external payable; /// @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 token function sweepToken( address token, uint256 amountMinimum, address recipient ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4 <0.9.0; import '../interfaces/pool/IAlgebraPoolErrors.sol'; /// @title Contains logic and constants for interacting with the plugin through hooks /// @dev Allows pool to check which hooks are enabled, as well as control the return selector library Plugins { function hasFlag(uint8 pluginConfig, uint256 flag) internal pure returns (bool res) { assembly { res := gt(and(pluginConfig, flag), 0) } } function shouldReturn(bytes4 selector, bytes4 expectedSelector) internal pure { if (selector != expectedSelector) revert IAlgebraPoolErrors.invalidHookResponse(expectedSelector); } uint256 internal constant BEFORE_SWAP_FLAG = 1; uint256 internal constant AFTER_SWAP_FLAG = 1 << 1; uint256 internal constant BEFORE_POSITION_MODIFY_FLAG = 1 << 2; uint256 internal constant AFTER_POSITION_MODIFY_FLAG = 1 << 3; uint256 internal constant BEFORE_FLASH_FLAG = 1 << 4; uint256 internal constant AFTER_FLASH_FLAG = 1 << 5; uint256 internal constant AFTER_INIT_FLAG = 1 << 6; uint256 internal constant DYNAMIC_FEE = 1 << 7; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library HexStrings { bytes16 internal constant ALPHABET = '0123456789abcdef'; /// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. /// @dev Credit to Open Zeppelin under MIT license https://github.com/OpenZeppelin/openzeppelin-contracts/blob/243adff49ce1700e0ecb99fe522fb16cff1d1ddc/contracts/utils/Strings.sol#L55 function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { unchecked { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = '0'; buffer[1] = 'x'; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = ALPHABET[value & 0xf]; value >>= 4; } require(value == 0, 'Strings: hex length insufficient'); return string(buffer); } } function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { unchecked { bytes memory buffer = new bytes(2 * length); for (uint256 i = buffer.length; i > 0; i--) { buffer[i - 1] = ALPHABET[value & 0xf]; value >>= 4; } return string(buffer); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; import '@openzeppelin/contracts/utils/Address.sol'; import '../interfaces/external/IERC1271.sol'; import '../interfaces/IERC721Permit.sol'; import './BlockTimestamp.sol'; /// @title ERC721 with permit /// @notice Nonfungible tokens that support an approve via signature, i.e. permit abstract contract ERC721Permit is BlockTimestamp, ERC721Enumerable, IERC721Permit { bytes32 private constant _TYPE_HASH = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'); /// @dev Gets the current nonce for a token ID and then increments it, returning the original value function _getAndIncrementNonce(uint256 tokenId) internal virtual returns (uint256); /// @dev The hash of the name used in the permit signature verification bytes32 private immutable nameHash; /// @dev The hash of the version string used in the permit signature verification bytes32 private immutable versionHash; bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; /// @notice Computes the nameHash and versionHash constructor(string memory name_, string memory symbol_, string memory version_) ERC721(name_, symbol_) { nameHash = keccak256(bytes(name_)); versionHash = keccak256(bytes(version_)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /// @inheritdoc IERC721Permit function DOMAIN_SEPARATOR() public view override returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, nameHash, versionHash, block.chainid, address(this))); } /// @inheritdoc IERC721Permit bytes32 public constant override PERMIT_TYPEHASH = keccak256('Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)'); /// @inheritdoc IERC721Permit function permit( address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable override { require(_blockTimestamp() <= deadline, 'Permit expired'); bytes32 digest = keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, _getAndIncrementNonce(tokenId), deadline)) ) ); address owner = ownerOf(tokenId); require(spender != owner, 'Approval to current owner'); if (Address.isContract(owner)) { _checkAuthorization(IERC1271(owner).isValidSignature(digest, abi.encodePacked(r, s, v)) == 0x1626ba7e); } else { address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0), 'Invalid signature'); _checkAuthorization(recoveredAddress == owner); } _approve(spender, tokenId); } function _checkAuthorization(bool isAuthorized) private pure { require(isAuthorized, 'Unauthorized'); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; library PositionKey { /// @dev Returns the key of the position in the core library function compute( address owner, int24 bottomTick, int24 topTick ) internal pure returns (bytes32 key) { assembly { key := or(shl(24, or(shl(24, owner), and(bottomTick, 0xFFFFFF))), and(topTick, 0xFFFFFF)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../interfaces/INonfungiblePositionManager.sol'; contract NonfungiblePositionManagerPositionsGasTest { INonfungiblePositionManager immutable nonfungiblePositionManager; constructor(INonfungiblePositionManager _nonfungiblePositionManager) { nonfungiblePositionManager = _nonfungiblePositionManager; } function getGasCostOfPositions(uint256 tokenId) external view returns (uint256) { uint256 gasBefore = gasleft(); nonfungiblePositionManager.positions(tokenId); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; pragma abicoder v1; import '@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol'; contract TestERC20 is ERC20Permit { uint256 fee; constructor(uint256 amountToMint) ERC20('Test ERC20', 'TEST') ERC20Permit('Test ERC20') { _mint(msg.sender, amountToMint); } function setFee(uint256 newFee) external { fee = newFee; } function _transfer(address owner, address to, uint256 amount) internal override { uint256 _fee = fee; if (_fee != 0) { uint256 collectedFee = (amount * _fee) / 1000; amount = amount - collectedFee; super._transfer(owner, address(this), collectedFee); } super._transfer(owner, to, amount); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import {IAlgebraCustomPoolEntryPoint, IAlgebraPluginFactory} from './interfaces/IAlgebraCustomPoolEntryPoint.sol'; import {IAlgebraPool} from '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import {IAlgebraFactory} from '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; /// @title Algebra custom pool entry point /// @notice Is used to create custom pools /// @dev Version: Algebra Integral 1.2.1 contract AlgebraCustomPoolEntryPoint is IAlgebraCustomPoolEntryPoint { /// @inheritdoc IAlgebraCustomPoolEntryPoint address public immutable override factory; modifier onlyCustomDeployer(address pool) { _checkIfDeployer(pool); _; } constructor(address _factory) { require(_factory != address(0)); factory = _factory; } /// @inheritdoc IAlgebraCustomPoolEntryPoint function createCustomPool( address deployer, address creator, address tokenA, address tokenB, bytes calldata data ) external override returns (address customPool) { require(msg.sender == deployer, 'Only deployer'); return IAlgebraFactory(factory).createCustomPool(deployer, creator, tokenA, tokenB, data); } /// @inheritdoc IAlgebraPluginFactory function beforeCreatePoolHook( address pool, address creator, address deployer, address token0, address token1, bytes calldata data ) external override returns (address) { require(msg.sender == factory, 'Only factory'); // all additional custom logic should be implemented in `deployer` smart contract return IAlgebraPluginFactory(deployer).beforeCreatePoolHook(pool, creator, deployer, token0, token1, data); } /// @inheritdoc IAlgebraPluginFactory function afterCreatePoolHook(address plugin, address pool, address deployer) external override { require(msg.sender == factory, 'Only factory'); IAlgebraPluginFactory(deployer).afterCreatePoolHook(plugin, pool, deployer); } // ####### Permissioned actions ####### // AlgebraCustomPoolEntryPoint must have a "POOLS_ADMINISTRATOR" role to be able to use permissioned actions /// @inheritdoc IAlgebraCustomPoolEntryPoint function setTickSpacing(address pool, int24 newTickSpacing) external override onlyCustomDeployer(pool) { IAlgebraPool(pool).setTickSpacing(newTickSpacing); } /// @inheritdoc IAlgebraCustomPoolEntryPoint function setPlugin(address pool, address newPluginAddress) external override onlyCustomDeployer(pool) { IAlgebraPool(pool).setPlugin(newPluginAddress); } /// @inheritdoc IAlgebraCustomPoolEntryPoint function setPluginConfig(address pool, uint8 newConfig) external override onlyCustomDeployer(pool) { IAlgebraPool(pool).setPluginConfig(newConfig); } /// @inheritdoc IAlgebraCustomPoolEntryPoint function setFee(address pool, uint16 newFee) external override onlyCustomDeployer(pool) { IAlgebraPool(pool).setFee(newFee); } function _checkIfDeployer(address pool) internal view { address token0 = IAlgebraPool(pool).token0(); address token1 = IAlgebraPool(pool).token1(); require(pool == IAlgebraFactory(factory).customPoolByPair(msg.sender, token0, token1), 'Only deployer'); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializing the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import './MockPlugin.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/plugin/IAlgebraPluginFactory.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; contract MockPluginFactory is IAlgebraPluginFactory { address public immutable algebraFactory; mapping(address poolAddress => address pluginAddress) public pluginByPool; constructor(address _algebraFactory) { algebraFactory = _algebraFactory; } /// @inheritdoc IAlgebraPluginFactory function beforeCreatePoolHook( address pool, address, address, address, address, bytes calldata ) external override returns (address) { require(msg.sender == algebraFactory); return _createPlugin(pool); } /// @inheritdoc IAlgebraPluginFactory function afterCreatePoolHook(address, address, address) external view override { require(msg.sender == algebraFactory); } // function createPluginForExistingPool(address token0, address token1) external override returns (address) { // IAlgebraFactory factory = IAlgebraFactory(algebraFactory); // require(factory.hasRoleOrOwner(factory.POOLS_ADMINISTRATOR_ROLE(), msg.sender)); // address pool = factory.poolByPair(token0, token1); // require(pool != address(0), 'Pool not exist'); // return _createPlugin(pool); // } function _createPlugin(address pool) internal returns (address) { require(pluginByPool[pool] == address(0), 'Already created'); MockPlugin mockPlugin = new MockPlugin(); pluginByPool[pool] = address(mockPlugin); return address(mockPlugin); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import './TestERC20.sol'; import '../interfaces/external/IERC20PermitAllowed.sol'; // has a fake permit that just uses the other signature type for type(uint256).max contract TestERC20PermitAllowed is TestERC20, IERC20PermitAllowed { constructor(uint256 amountToMint) TestERC20(amountToMint) {} function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external override { require(this.nonces(holder) == nonce, 'TestERC20PermitAllowed::permit: wrong nonce'); permit(holder, spender, allowed ? type(uint256).max : 0, expiry, v, r, s); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol'; contract TestERC20Metadata is ERC20Permit { constructor(uint256 amountToMint, string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) { _mint(msg.sender, amountToMint); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Creates and initializes Algebra Pools /// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that /// require the pool to exist. /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IPoolInitializer { /// @notice Creates a new pool if it does not exist, then initializes if not initialized /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool /// @param token0 The contract address of token0 of the pool /// @param token1 The contract address of token1 of the pool /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value /// @param data Data for plugin initialization /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary function createAndInitializePoolIfNecessary( address token0, address token1, address deployer, uint160 sqrtPriceX96, bytes calldata data ) external payable returns (address pool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Provides functions for deriving a pool address from the poolDeployer and tokens /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { bytes32 internal constant POOL_INIT_CODE_HASH = 0xa18736c3ee97fe3c96c9428c0cc2a9116facec18e84f95f9da30543f8238a782; /// @notice The identifying key of the pool struct PoolKey { address deployer; address token0; address token1; } /// @notice Returns PoolKey: the ordered tokens /// @param deployer The custom pool deployer address /// @param tokenA The first token of a pool, unsorted /// @param tokenB The second token of a pool, unsorted /// @return Poolkey The pool details with ordered token0 and token1 assignments function getPoolKey(address deployer, address tokenA, address tokenB) internal pure returns (PoolKey memory) { if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); return PoolKey({deployer: deployer, token0: tokenA, token1: tokenB}); } /// @notice Deterministically computes the pool address given the poolDeployer and PoolKey /// @param poolDeployer The Algebra poolDeployer contract address /// @param key The PoolKey /// @return pool The contract address of the Algebra pool function computeAddress(address poolDeployer, PoolKey memory key) internal pure returns (address pool) { require(key.token0 < key.token1, 'Invalid order of tokens'); pool = address( uint160( uint256( keccak256( abi.encodePacked( hex'ff', poolDeployer, keccak256( key.deployer == address(0) ? abi.encode(key.token0, key.token1) : abi.encode(key.deployer, key.token0, key.token1) ), POOL_INIT_CODE_HASH ) ) ) ) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that can change /// @dev Important security note: when using this data by external contracts, it is necessary to take into account the possibility /// of manipulation (including read-only reentrancy). /// This interface is based on the UniswapV3 interface, credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolState { /// @notice Safely get most important state values of Algebra Integral AMM /// @dev Several values exposed as a single method to save gas when accessed externally. /// **Important security note: this method checks reentrancy lock and should be preferred in most cases**. /// @return sqrtPrice The current price of the pool as a sqrt(dToken1/dToken0) Q64.96 value /// @return tick The current global tick of the pool. May not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick boundary /// @return lastFee The current (last known) pool fee value in hundredths of a bip, i.e. 1e-6 (so '100' is '0.01%'). May be obsolete if using dynamic fee plugin /// @return pluginConfig The current plugin config as bitmap. Each bit is responsible for enabling/disabling the hooks, the last bit turns on/off dynamic fees logic /// @return activeLiquidity The currently in-range liquidity available to the pool /// @return nextTick The next initialized tick after current global tick /// @return previousTick The previous initialized tick before (or at) current global tick function safelyGetStateOfAMM() external view returns (uint160 sqrtPrice, int24 tick, uint16 lastFee, uint8 pluginConfig, uint128 activeLiquidity, int24 nextTick, int24 previousTick); /// @notice Allows to easily get current reentrancy lock status /// @dev can be used to prevent read-only reentrancy. /// This method just returns `globalState.unlocked` value /// @return unlocked Reentrancy lock flag, true if the pool currently is unlocked, otherwise - false function isUnlocked() external view returns (bool unlocked); // ! IMPORTANT security note: the pool state can be manipulated. // ! The following methods do not check reentrancy lock themselves. /// @notice The globalState structure in the pool stores many values but requires only one slot /// and is exposed as a single method to save gas when accessed externally. /// @dev **important security note: caller should check `unlocked` flag to prevent read-only reentrancy** /// @return price The current price of the pool as a sqrt(dToken1/dToken0) Q64.96 value /// @return tick The current tick of the pool, i.e. according to the last tick transition that was run /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick boundary /// @return lastFee The current (last known) pool fee value in hundredths of a bip, i.e. 1e-6 (so '100' is '0.01%'). May be obsolete if using dynamic fee plugin /// @return pluginConfig The current plugin config as bitmap. Each bit is responsible for enabling/disabling the hooks, the last bit turns on/off dynamic fees logic /// @return communityFee The community fee represented as a percent of all collected fee in thousandths, i.e. 1e-3 (so 100 is 10%) /// @return unlocked Reentrancy lock flag, true if the pool currently is unlocked, otherwise - false function globalState() external view returns (uint160 price, int24 tick, uint16 lastFee, uint8 pluginConfig, uint16 communityFee, bool unlocked); /// @notice Look up information about a specific tick in the pool /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @param tick The tick to look up /// @return liquidityTotal The total amount of position liquidity that uses the pool either as tick lower or tick upper /// @return liquidityDelta How much liquidity changes when the pool price crosses the tick /// @return prevTick The previous tick in tick list /// @return nextTick The next tick in tick list /// @return outerFeeGrowth0Token The fee growth on the other side of the tick from the current tick in token0 /// @return outerFeeGrowth1Token The fee growth on the other side of the tick from the current tick in token1 /// In addition, these values are only relative and must be used only in comparison to previous snapshots for /// a specific position. function ticks( int24 tick ) external view returns ( uint256 liquidityTotal, int128 liquidityDelta, int24 prevTick, int24 nextTick, uint256 outerFeeGrowth0Token, uint256 outerFeeGrowth1Token ); /// @notice The timestamp of the last sending of tokens to vault/plugin /// @return The timestamp truncated to 32 bits function lastFeeTransferTimestamp() external view returns (uint32); /// @notice The amounts of token0 and token1 that will be sent to the vault /// @dev Will be sent FEE_TRANSFER_FREQUENCY after communityFeeLastTimestamp /// @return communityFeePending0 The amount of token0 that will be sent to the vault /// @return communityFeePending1 The amount of token1 that will be sent to the vault function getCommunityFeePending() external view returns (uint128 communityFeePending0, uint128 communityFeePending1); /// @notice The amounts of token0 and token1 that will be sent to the plugin /// @dev Will be sent FEE_TRANSFER_FREQUENCY after feeLastTransferTimestamp /// @return pluginFeePending0 The amount of token0 that will be sent to the plugin /// @return pluginFeePending1 The amount of token1 that will be sent to the plugin function getPluginFeePending() external view returns (uint128 pluginFeePending0, uint128 pluginFeePending1); /// @notice Returns the address of currently used plugin /// @dev The plugin is subject to change /// @return pluginAddress The address of currently used plugin function plugin() external view returns (address pluginAddress); /// @notice The contract to which community fees are transferred /// @return communityVaultAddress The communityVault address function communityVault() external view returns (address communityVaultAddress); /// @notice Returns 256 packed tick initialized boolean values. See TickTree for more information /// @param wordPosition Index of 256-bits word with ticks /// @return The 256-bits word with packed ticks info function tickTable(int16 wordPosition) external view returns (uint256); /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool /// @dev This value can overflow the uint256 /// @return The fee growth accumulator for token0 function totalFeeGrowth0Token() external view returns (uint256); /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool /// @dev This value can overflow the uint256 /// @return The fee growth accumulator for token1 function totalFeeGrowth1Token() external view returns (uint256); /// @notice The current pool fee value /// @dev In case dynamic fee is enabled in the pool, this method will call the plugin to get the current fee. /// If the plugin implements complex fee logic, this method may return an incorrect value or revert. /// In this case, see the plugin implementation and related documentation. /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return currentFee The current pool fee value in hundredths of a bip, i.e. 1e-6 function fee() external view returns (uint16 currentFee); /// @notice The tracked token0 and token1 reserves of pool /// @dev If at any time the real balance is larger, the excess will be transferred to liquidity providers as additional fee. /// If the balance exceeds uint128, the excess will be sent to the communityVault. /// @return reserve0 The last known reserve of token0 /// @return reserve1 The last known reserve of token1 function getReserves() external view returns (uint128 reserve0, uint128 reserve1); /// @notice Returns the information about a position by the position's key /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @param key The position's key is a packed concatenation of the owner address, bottomTick and topTick indexes /// @return liquidity The amount of liquidity in the position /// @return innerFeeGrowth0Token Fee growth of token0 inside the tick range as of the last mint/burn/poke /// @return innerFeeGrowth1Token Fee growth of token1 inside the tick range as of the last mint/burn/poke /// @return fees0 The computed amount of token0 owed to the position as of the last mint/burn/poke /// @return fees1 The computed amount of token1 owed to the position as of the last mint/burn/poke function positions( bytes32 key ) external view returns (uint256 liquidity, uint256 innerFeeGrowth0Token, uint256 innerFeeGrowth1Token, uint128 fees0, uint128 fees1); /// @notice The currently in range liquidity available to the pool /// @dev This value has no relationship to the total liquidity across all ticks. /// Returned value cannot exceed type(uint128).max /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return The current in range liquidity function liquidity() external view returns (uint128); /// @notice The current tick spacing /// @dev Ticks can only be initialized by new mints at multiples of this value /// e.g.: a tickSpacing of 60 means ticks can be initialized every 60th tick, i.e., ..., -120, -60, 0, 60, 120, ... /// However, tickspacing can be changed after the ticks have been initialized. /// This value is an int24 to avoid casting even though it is always positive. /// @return The current tick spacing function tickSpacing() external view returns (int24); /// @notice The previous initialized tick before (or at) current global tick /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return The previous initialized tick function prevTickGlobal() external view returns (int24); /// @notice The next initialized tick after current global tick /// @dev **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return The next initialized tick function nextTickGlobal() external view returns (int24); /// @notice The root of tick search tree /// @dev Each bit corresponds to one node in the second layer of tick tree: '1' if node has at least one active bit. /// **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return The root of tick search tree as bitmap function tickTreeRoot() external view returns (uint32); /// @notice The second layer of tick search tree /// @dev Each bit in node corresponds to one node in the leafs layer (`tickTable`) of tick tree: '1' if leaf has at least one active bit. /// **important security note: caller should check reentrancy lock to prevent read-only reentrancy** /// @return The node of tick search tree second layer function tickTreeSecondLayer(int16) external view returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import './PeripheryImmutableState.sol'; import '../interfaces/IPoolInitializer.sol'; import '../libraries/PoolInteraction.sol'; /// @title Creates and initializes Algebra Pools /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PoolInitializer is IPoolInitializer, PeripheryImmutableState { using PoolInteraction for IAlgebraPool; /// @inheritdoc IPoolInitializer function createAndInitializePoolIfNecessary( address token0, address token1, address deployer, uint160 sqrtPriceX96, bytes calldata data ) external payable override returns (address pool) { require(token0 < token1, 'Invalid order of tokens'); IAlgebraFactory _factory = IAlgebraFactory(factory); if (deployer == address(0)) pool = _factory.poolByPair(token0, token1); else { pool = _factory.customPoolByPair(deployer, token0, token1); } if (pool == address(0)) { if (deployer == address(0)) { pool = _factory.createPool(token0, token1, data); _initializePool(pool, sqrtPriceX96); } } else { uint160 sqrtPriceX96Existing = IAlgebraPool(pool)._getSqrtPrice(); if (sqrtPriceX96Existing == 0) { _initializePool(pool, sqrtPriceX96); } } } function _initializePool(address pool, uint160 initPrice) private { IAlgebraPool(pool).initialize(initPrice); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../libraries/PoolAddress.sol'; contract PoolAddressTest { function POOL_INIT_CODE_HASH() external pure returns (bytes32) { return PoolAddress.POOL_INIT_CODE_HASH; } function computeAddress( address factory, address token0, address token1, address deployer, uint24 fee ) external pure returns (address) { fee; return PoolAddress.computeAddress( factory, PoolAddress.PoolKey({deployer: deployer, token0: token0, token1: token1}) ); } function getGasCostOfComputeAddress( address factory, address token0, address token1, address deployer, uint24 fee ) external view returns (uint256) { fee; uint256 gasBefore = gasleft(); PoolAddress.computeAddress(factory, PoolAddress.PoolKey({deployer: deployer, token0: token0, token1: token1})); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0 = a * b; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { assembly { result := div(prod0, denominator) } return result; } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod // Subtract 256 bit remainder from 512 bit number assembly { let remainder := mulmod(a, b, denominator) prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (0 - denominator) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the preconditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { if (a == 0 || ((result = a * b) / a == b)) { require(denominator > 0); assembly { result := add(div(result, denominator), gt(mod(result, denominator), 0)) } } else { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } } /// @notice Returns ceil(x / y) /// @dev division by 0 has unspecified behavior, and must be checked externally /// @param x The dividend /// @param y The divisor /// @return z The quotient, ceil(x / y) function unsafeDivRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := add(div(x, y), gt(mod(x, y), 0)) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import './BlockTimestamp.sol'; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PeripheryValidation is BlockTimestamp { modifier checkDeadline(uint256 deadline) { _checkDeadline(deadline); _; } function _checkDeadline(uint256 deadline) private view { require(_blockTimestamp() <= deadline, 'Transaction too old'); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Events emitted by a pool /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolEvents { /// @notice Emitted exactly once by a pool when #initialize is first called on the pool /// @dev Mint/Burn/Swaps cannot be emitted by the pool before Initialize /// @param price The initial sqrt price of the pool, as a Q64.96 /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool event Initialize(uint160 price, int24 tick); /// @notice Emitted when liquidity is minted for a given position /// @param sender The address that minted the liquidity /// @param owner The owner of the position and recipient of any minted liquidity /// @param bottomTick The lower tick of the position /// @param topTick The upper tick of the position /// @param liquidityAmount The amount of liquidity minted to the position range /// @param amount0 How much token0 was required for the minted liquidity /// @param amount1 How much token1 was required for the minted liquidity event Mint( address sender, address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1 ); /// @notice Emitted when fees are collected by the owner of a position /// @param owner The owner of the position for which fees are collected /// @param recipient The address that received fees /// @param bottomTick The lower tick of the position /// @param topTick The upper tick of the position /// @param amount0 The amount of token0 fees collected /// @param amount1 The amount of token1 fees collected event Collect(address indexed owner, address recipient, int24 indexed bottomTick, int24 indexed topTick, uint128 amount0, uint128 amount1); /// @notice Emitted when a position's liquidity is removed /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect /// @param owner The owner of the position for which liquidity is removed /// @param bottomTick The lower tick of the position /// @param topTick The upper tick of the position /// @param liquidityAmount The amount of liquidity to remove /// @param amount0 The amount of token0 withdrawn /// @param amount1 The amount of token1 withdrawn /// @param pluginFee The fee to be sent to the plugin event Burn( address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1, uint24 pluginFee ); /// @notice Emitted by the pool for any swaps between token0 and token1 /// @param sender The address that initiated the swap call, and that received the callback /// @param recipient The address that received the output of the swap /// @param amount0 The delta of the token0 balance of the pool /// @param amount1 The delta of the token1 balance of the pool /// @param price The sqrt(price) of the pool after the swap, as a Q64.96 /// @param liquidity The liquidity of the pool after the swap /// @param tick The log base 1.0001 of price of the pool after the swap /// @param overrideFee The fee to be applied to the trade /// @param pluginFee The fee to be sent to the plugin event Swap( address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 price, uint128 liquidity, int24 tick, uint24 overrideFee, uint24 pluginFee ); /// @notice Emitted by the pool for any flashes of token0/token1 /// @param sender The address that initiated the swap call, and that received the callback /// @param recipient The address that received the tokens from flash /// @param amount0 The amount of token0 that was flashed /// @param amount1 The amount of token1 that was flashed /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1); /// @notice Emitted when the pool has higher balances than expected. /// Any excess of tokens will be distributed between liquidity providers as fee. /// @dev Fees after flash also will trigger this event due to mechanics of flash. /// @param amount0 The excess of token0 /// @param amount1 The excess of token1 event ExcessTokens(uint256 amount0, uint256 amount1); /// @notice Emitted when the community fee is changed by the pool /// @param communityFeeNew The updated value of the community fee in thousandths (1e-3) event CommunityFee(uint16 communityFeeNew); /// @notice Emitted when the tick spacing changes /// @param newTickSpacing The updated value of the new tick spacing event TickSpacing(int24 newTickSpacing); /// @notice Emitted when the plugin address changes /// @param newPluginAddress New plugin address event Plugin(address newPluginAddress); /// @notice Emitted when the plugin config changes /// @param newPluginConfig New plugin config event PluginConfig(uint8 newPluginConfig); /// @notice Emitted when the fee changes inside the pool /// @param fee The current fee in hundredths of a bip, i.e. 1e-6 event Fee(uint16 fee); /// @notice Emitted when the community vault address changes /// @param newCommunityVault New community vault event CommunityVault(address newCommunityVault); /// @notice Emitted when the plugin does skim the excess of tokens /// @param to THe receiver of tokens (plugin) /// @param amount0 The amount of token0 /// @param amount1 The amount of token1 event Skim(address indexed to, uint256 amount0, uint256 amount1); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissionless pool actions /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolActions { /// @notice Sets the initial price for the pool /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value /// @dev Initialization should be done in one transaction with pool creation to avoid front-running /// @param initialPrice The initial sqrt price of the pool as a Q64.96 function initialize(uint160 initialPrice) external; /// @notice Adds liquidity for the given recipient/bottomTick/topTick position /// @dev The caller of this method receives a callback in the form of IAlgebraMintCallback#algebraMintCallback /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends /// on bottomTick, topTick, the amount of liquidity, and the current price. /// @param leftoversRecipient The address which will receive potential surplus of paid tokens /// @param recipient The address for which the liquidity will be created /// @param bottomTick The lower tick of the position in which to add liquidity /// @param topTick The upper tick of the position in which to add liquidity /// @param liquidityDesired The desired amount of liquidity to mint /// @param data Any data that should be passed through to the callback /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback /// @return liquidityActual The actual minted amount of liquidity function mint( address leftoversRecipient, address recipient, int24 bottomTick, int24 topTick, uint128 liquidityDesired, bytes calldata data ) external returns (uint256 amount0, uint256 amount1, uint128 liquidityActual); /// @notice Collects tokens owed to a position /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. /// @param recipient The address which should receive the fees collected /// @param bottomTick The lower tick of the position for which to collect fees /// @param topTick The upper tick of the position for which to collect fees /// @param amount0Requested How much token0 should be withdrawn from the fees owed /// @param amount1Requested How much token1 should be withdrawn from the fees owed /// @return amount0 The amount of fees collected in token0 /// @return amount1 The amount of fees collected in token1 function collect( address recipient, int24 bottomTick, int24 topTick, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 /// @dev Fees must be collected separately via a call to #collect /// @param bottomTick The lower tick of the position for which to burn liquidity /// @param topTick The upper tick of the position for which to burn liquidity /// @param amount How much liquidity to burn /// @param data Any data that should be passed through to the plugin /// @return amount0 The amount of token0 sent to the recipient /// @return amount1 The amount of token1 sent to the recipient function burn(int24 bottomTick, int24 topTick, uint128 amount, bytes calldata data) external returns (uint256 amount0, uint256 amount1); /// @notice Swap token0 for token1, or token1 for token0 /// @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback#algebraSwapCallback /// @param recipient The address to receive the output of the swap /// @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 /// @param amountRequired The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) /// @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param data Any data to be passed through to the callback. If using the Router it should contain SwapRouter#SwapCallbackData /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive function swap( address recipient, bool zeroToOne, int256 amountRequired, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /// @notice Swap token0 for token1, or token1 for token0 with prepayment /// @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback#algebraSwapCallback /// caller must send tokens in callback before swap calculation /// the actually sent amount of tokens is used for further calculations /// @param leftoversRecipient The address which will receive potential surplus of paid tokens /// @param recipient The address to receive the output of the swap /// @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 /// @param amountToSell The amount of the swap, only positive (exact input) amount allowed /// @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param data Any data to be passed through to the callback. If using the Router it should contain SwapRouter#SwapCallbackData /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive function swapWithPaymentInAdvance( address leftoversRecipient, address recipient, bool zeroToOne, int256 amountToSell, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback /// @dev The caller of this method receives a callback in the form of IAlgebraFlashCallback#algebraFlashCallback /// @dev All excess tokens paid in the callback are distributed to currently in-range liquidity providers as an additional fee. /// If there are no in-range liquidity providers, the fee will be transferred to the first active provider in the future /// @param recipient The address which will receive the token0 and token1 amounts /// @param amount0 The amount of token0 to send /// @param amount1 The amount of token1 to send /// @param data Any data to be passed through to the callback function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0 <0.9.0; /// @title Abstract contract with modified blockTimestamp functionality /// @notice Allows the pool and other contracts to get a timestamp truncated to 32 bits /// @dev Can be overridden in tests to make testing easier abstract contract Timestamp { /// @dev This function is created for testing by overriding it. /// @return A timestamp converted to uint32 function _blockTimestamp() internal view virtual returns (uint32) { return uint32(block.timestamp); // truncation is desired } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4 <0.9.0; import '../interfaces/pool/IAlgebraPoolErrors.sol'; import './TickMath.sol'; import './TokenDeltaMath.sol'; /// @title Math library for liquidity /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library LiquidityMath { /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { unchecked { if (y < 0) { if ((z = x - uint128(-y)) >= x) revert IAlgebraPoolErrors.liquiditySub(); } else { if ((z = x + uint128(y)) < x) revert IAlgebraPoolErrors.liquidityAdd(); } } } function getAmountsForLiquidity( int24 bottomTick, int24 topTick, int128 liquidityDelta, int24 currentTick, uint160 currentPrice ) internal pure returns (uint256 amount0, uint256 amount1, int128 globalLiquidityDelta) { uint160 priceAtBottomTick = TickMath.getSqrtRatioAtTick(bottomTick); uint160 priceAtTopTick = TickMath.getSqrtRatioAtTick(topTick); int256 amount0Int; int256 amount1Int; if (currentTick < bottomTick) { // If current tick is less than the provided bottom one then only the token0 has to be provided amount0Int = TokenDeltaMath.getToken0Delta(priceAtBottomTick, priceAtTopTick, liquidityDelta); } else if (currentTick < topTick) { amount0Int = TokenDeltaMath.getToken0Delta(currentPrice, priceAtTopTick, liquidityDelta); amount1Int = TokenDeltaMath.getToken1Delta(priceAtBottomTick, currentPrice, liquidityDelta); globalLiquidityDelta = liquidityDelta; } else { // If current tick is greater than the provided top one then only the token1 has to be provided amount1Int = TokenDeltaMath.getToken1Delta(priceAtBottomTick, priceAtTopTick, liquidityDelta); } unchecked { (amount0, amount1) = liquidityDelta < 0 ? (uint256(-amount0Int), uint256(-amount1Int)) : (uint256(amount0Int), uint256(amount1Int)); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title QuoterV2 Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps. /// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap. /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IQuoterV2 { /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair /// @param amountInRequired The desired amount of the first token to swap /// @return amountOutList The amount of the last token that would be received /// @return amountInList The amount of the last token that should be paid /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes /// @return feeList List of the fee values used for swaps in the path function quoteExactInput( bytes memory path, uint256 amountInRequired ) external returns ( uint256[] memory amountOutList, uint256[] memory amountInList, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate, uint16[] memory feeList ); struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; address deployer; uint256 amountIn; uint160 limitSqrtPrice; } /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// amountIn The desired input amount /// limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received /// @return amountIn The amount of the `tokenIn` that should be paid /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed /// @return gasEstimate The estimate of the gas that the swap consumes /// @return fee The fee value used for swap in the pool function quoteExactInputSingle( QuoteExactInputSingleParams memory params ) external returns ( uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate, uint16 fee ); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair. Path must be provided in reverse order /// @param amountOutRequired The amount of the last token to receive /// @return amountOutList The amount of the last token that would be received /// @return amountInList The amount of first token required to be paid /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes /// @return feeList List of the fee values used for swaps in the path function quoteExactOutput( bytes memory path, uint256 amountOutRequired ) external returns ( uint256[] memory amountOutList, uint256[] memory amountInList, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate, uint16[] memory feeList ); struct QuoteExactOutputSingleParams { address tokenIn; address tokenOut; address deployer; uint256 amount; uint160 limitSqrtPrice; } /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// amountOut The desired output amount /// limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of the last token that would be received /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed /// @return gasEstimate The estimate of the gas that the swap consumes /// @return fee The fee value used for swap in the pool function quoteExactOutputSingle( QuoteExactOutputSingleParams memory params ) external returns ( uint256 amountOut, uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate, uint16 fee ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; pragma abicoder v2; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '../lens/TickLens.sol'; /// @title Tick Lens contract contract TickLensTest is TickLens { function getGasCostOfGetPopulatedTicksInWord(address pool, int16 tickTableIndex) external view returns (uint256) { uint256 gasBefore = gasleft(); getPopulatedTicksInWord(pool, tickTableIndex); return gasBefore - gasleft(); } function getGasCostOfGetNextActiveTicks( address pool, int24 startingTick, uint256 amount, bool upperDirection ) external view returns (uint256) { uint256 gasBefore = gasleft(); getNextActiveTicks(pool, startingTick, amount, upperDirection); return gasBefore - gasleft(); } function getGasCostOfGetClosestActiveTicks(address pool, int24 targetTick) external view returns (uint256) { uint256 gasBefore = gasleft(); getClosestActiveTicks(pool, targetTick); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that never changes /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolImmutables { /// @notice The Algebra factory contract, which must adhere to the IAlgebraFactory interface /// @return The contract address function factory() external view returns (address); /// @notice The first of the two tokens of the pool, sorted by address /// @return The token contract address function token0() external view returns (address); /// @notice The second of the two tokens of the pool, sorted by address /// @return The token contract address function token1() external view returns (address); /// @notice The maximum amount of position liquidity that can use any tick in the range /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool /// @return The max amount of liquidity per tick function maxLiquidityPerTick() external view returns (uint128); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../libraries/PositionValue.sol'; import '../interfaces/INonfungiblePositionManager.sol'; contract PositionValueTest { function total( INonfungiblePositionManager nft, uint256 tokenId, uint160 sqrtRatioX96 ) external view returns (uint256 amount0, uint256 amount1) { return PositionValue.total(nft, tokenId, sqrtRatioX96); } function principal( INonfungiblePositionManager nft, uint256 tokenId, uint160 sqrtRatioX96 ) external view returns (uint256 amount0, uint256 amount1) { return PositionValue.principal(nft, tokenId, sqrtRatioX96); } function fees( INonfungiblePositionManager nft, uint256 tokenId ) external view returns (uint256 amount0, uint256 amount1) { return PositionValue.fees(nft, tokenId); } function totalGas( INonfungiblePositionManager nft, uint256 tokenId, uint160 sqrtRatioX96 ) external view returns (uint256) { uint256 gasBefore = gasleft(); PositionValue.total(nft, tokenId, sqrtRatioX96); return gasBefore - gasleft(); } function principalGas( INonfungiblePositionManager nft, uint256 tokenId, uint160 sqrtRatioX96 ) external view returns (uint256) { uint256 gasBefore = gasleft(); PositionValue.principal(nft, tokenId, sqrtRatioX96); return gasBefore - gasleft(); } function feesGas(INonfungiblePositionManager nft, uint256 tokenId) external view returns (uint256) { uint256 gasBefore = gasleft(); PositionValue.fees(nft, tokenId); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: GPL-2.0-or-later /** * @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 slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { unchecked { 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) { unchecked { require(_bytes.length >= _start + 20, 'toAddress_outOfBounds'); } address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { unchecked { 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: 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: GPL-2.0-or-later pragma solidity =0.8.20; import '../interfaces/IMulticall.sol'; /// @title Multicall /// @notice Enables calling multiple methods in a single call to the contract abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) external payable override returns (bytes[] memory results) { results = new bytes[](data.length); unchecked { for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Look for revert reason and bubble it up if present require(result.length > 0); // The easiest way to bubble the revert reason is using memory via assembly assembly ('memory-safe') { revert(add(32, result), mload(result)) } } results[i] = result; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/base/common/Timestamp.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/Plugins.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraFactory.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/plugin/IAlgebraPlugin.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/pool/IAlgebraPoolState.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; contract CustomPlugin is Timestamp, IAlgebraPlugin { using Plugins for uint8; address public pool; bytes32 public constant ALGEBRA_BASE_PLUGIN_MANAGER = keccak256('ALGEBRA_BASE_PLUGIN_MANAGER'); function _getPoolState() internal view returns (uint160 price, int24 tick, uint16 fee, uint8 pluginConfig) { (price, tick, fee, pluginConfig, , ) = IAlgebraPoolState(pool).globalState(); } /// @inheritdoc IAlgebraPlugin uint8 public constant override defaultPluginConfig = uint8(Plugins.BEFORE_SWAP_FLAG | Plugins.AFTER_SWAP_FLAG | Plugins.DYNAMIC_FEE); function beforeInitialize(address, uint160) external override returns (bytes4) { pool = msg.sender; _updatePluginConfigInPool(); return IAlgebraPlugin.beforeInitialize.selector; } function afterInitialize(address, uint160, int24) external override returns (bytes4) { _updatePluginConfigInPool(); return IAlgebraPlugin.afterInitialize.selector; } /// @dev unused function beforeModifyPosition( address, address, int24, int24, int128, bytes calldata ) external override returns (bytes4, uint24) { _updatePluginConfigInPool(); // should not be called, reset config return (IAlgebraPlugin.beforeModifyPosition.selector, 0); } /// @dev unused function afterModifyPosition( address, address, int24, int24, int128, uint256, uint256, bytes calldata ) external override returns (bytes4) { _updatePluginConfigInPool(); // should not be called, reset config return IAlgebraPlugin.afterModifyPosition.selector; } function beforeSwap( address, address, bool, int256, uint160, bool, bytes calldata ) external override returns (bytes4, uint24, uint24) { IAlgebraPool(pool).setFee(10000); return (IAlgebraPlugin.beforeSwap.selector, 0, 0); } function afterSwap( address, address, bool, int256, uint160, int256, int256, bytes calldata ) external override returns (bytes4) { IAlgebraPool(pool).setFee(100); return IAlgebraPlugin.afterSwap.selector; } function handlePluginFee(uint256, uint256) external pure returns (bytes4) { return IAlgebraPlugin.handlePluginFee.selector; } /// @dev unused function beforeFlash(address, address, uint256, uint256, bytes calldata) external override returns (bytes4) { _updatePluginConfigInPool(); // should not be called, reset config return IAlgebraPlugin.beforeFlash.selector; } /// @dev unused function afterFlash( address, address, uint256, uint256, uint256, uint256, bytes calldata ) external override returns (bytes4) { _updatePluginConfigInPool(); // should not be called, reset config return IAlgebraPlugin.afterFlash.selector; } function _updatePluginConfigInPool() internal { uint8 newPluginConfig = defaultPluginConfig; (, , , uint8 currentPluginConfig) = _getPoolState(); if (currentPluginConfig != newPluginConfig) { IAlgebraPool(pool).setPluginConfig(newPluginConfig); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-ERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./ERC20Permit.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) pragma solidity ^0.8.0; /** * @dev Provides a set of functions to operate with Base64 strings. * * _Available since v4.5._ */ library Base64 { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // Loads the table into memory string memory table = _TABLE; // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter // and split into 4 numbers of 6 bits. // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up // - `data.length + 2` -> Round up // - `/ 3` -> Number of 3-bytes chunks // - `4 *` -> 4 characters for each chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 32) // Run over the input, 3 bytes at a time for { let dataPtr := data let endPtr := add(data, mload(data)) } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 bytes (18 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F which is the number of // the previous character in the ASCII table prior to the Base64 Table // The result is then added to the table to get the character to write, // and finally write it in the result pointer but with a left shift // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import './PositionKey.sol'; /// @title Implements commonly used interactions with Algebra pool library PoolInteraction { function _getPositionInPool( IAlgebraPool pool, address owner, int24 tickLower, int24 tickUpper ) internal view returns ( uint256 liquidityAmount, uint256 innerFeeGrowth0Token, uint256 innerFeeGrowth1Token, uint128 fees0, uint128 fees1 ) { return pool.positions(PositionKey.compute(owner, tickLower, tickUpper)); } function _getSqrtPrice(IAlgebraPool pool) internal view returns (uint160 sqrtPriceX96) { (sqrtPriceX96, , , , , ) = pool.globalState(); } function _burnPositionInPool( IAlgebraPool pool, int24 tickLower, int24 tickUpper, uint128 liquidity ) internal returns (uint256 amount0, uint256 amount1) { return pool.burn(tickLower, tickUpper, liquidity, '0x0'); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../base/SelfPermit.sol'; /// @dev Same as SelfPermit but not abstract contract SelfPermitTest is SelfPermit { }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title The interface for the Algebra Vault Factory /// @notice This contract can be used for automatic vaults creation /// @dev Version: Algebra Integral interface IAlgebraVaultFactory { /// @notice returns address of the community fee vault for the pool /// @param pool the address of Algebra Integral pool /// @return communityFeeVault the address of community fee vault function getVaultForPool(address pool) external view returns (address communityFeeVault); /// @notice creates the community fee vault for the pool if needed /// @param pool the address of Algebra Integral pool /// @return communityFeeVault the address of community fee vault function createVaultForPool( address pool, address creator, address deployer, address token0, address token1 ) external returns (address communityFeeVault); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @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. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; import './AddressStringUtil.sol'; // produces token descriptors from inconsistent or absent ERC20 symbol implementations that can return string or bytes32 // this library will always produce a string symbol to represent the token library SafeERC20Namer { function bytes32ToString(bytes32 x) private pure returns (string memory) { unchecked { bytes memory bytesString = new bytes(32); uint256 charCount = 0; for (uint256 j = 0; j < 32; j++) { bytes1 char = x[j]; if (char != 0) { bytesString[charCount] = char; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (uint256 j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } } // assumes the data is in position 2 function parseStringData(bytes memory b) private pure returns (string memory) { unchecked { uint256 charCount = 0; // first parse the charCount out of the data for (uint256 i = 32; i < 64; i++) { charCount <<= 8; charCount += uint8(b[i]); } bytes memory bytesStringTrimmed = new bytes(charCount); for (uint256 i = 0; i < charCount; i++) { bytesStringTrimmed[i] = b[i + 64]; } return string(bytesStringTrimmed); } } // uses a heuristic to produce a token name from the address // the heuristic returns the full hex of the address string in upper case function addressToName(address token) private pure returns (string memory) { return AddressStringUtil.toAsciiString(token, 40); } // uses a heuristic to produce a token symbol from the address // the heuristic returns the first 6 hex of the address string in upper case function addressToSymbol(address token) private pure returns (string memory) { return AddressStringUtil.toAsciiString(token, 6); } // calls an external view token contract method that returns a symbol or name, and parses the output into a string function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) { (bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector)); // if not implemented, or returns empty data, return empty string if (!success || data.length == 0) { return ''; } // bytes32 data always has length 32 if (data.length == 32) { bytes32 decoded = abi.decode(data, (bytes32)); return bytes32ToString(decoded); } else if (data.length > 64) { return abi.decode(data, (string)); } return ''; } // attempts to extract the token symbol. if it does not implement symbol, returns a symbol derived from the address function tokenSymbol(address token) internal view returns (string memory) { // 0x95d89b41 = bytes4(keccak256("symbol()")) string memory symbol = callAndParseStringReturn(token, 0x95d89b41); if (bytes(symbol).length == 0) { // fallback to 6 uppercase hex of address return addressToSymbol(token); } return symbol; } // attempts to extract the token name. if it does not implement name, returns a name derived from the address function tokenName(address token) internal view returns (string memory) { // 0x06fdde03 = bytes4(keccak256("name()")) string memory name = callAndParseStringReturn(token, 0x06fdde03); if (bytes(name).length == 0) { // fallback to full hex of address return addressToName(token); } return name; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4 <0.9.0; import '../interfaces/pool/IAlgebraPoolErrors.sol'; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return price A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) /// at the given tick function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 price) { unchecked { // get abs value int24 absTickMask = tick >> (24 - 1); uint256 absTick = uint24((tick + absTickMask) ^ absTickMask); if (absTick > uint24(MAX_TICK)) revert IAlgebraPoolErrors.tickOutOfRange(); uint256 ratio = 0x100000000000000000000000000000000; if (absTick & 0x1 != 0) ratio = 0xfffcb933bd6fad37aa2d162d1a594001; if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick >= 0x40000) { if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; } if (tick > 0) { assembly { ratio := div(not(0), ratio) } } // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtRatio of the output price is always consistent price = uint160((ratio + 0xFFFFFFFF) >> 32); } } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case price < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param price The sqrt ratio for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio function getTickAtSqrtRatio(uint160 price) internal pure returns (int24 tick) { unchecked { // second inequality must be >= because the price can never reach the price at the max tick if (price < MIN_SQRT_RATIO || price >= MAX_SQRT_RATIO) revert IAlgebraPoolErrors.priceOutOfRange(); uint256 ratio = uint256(price) << 32; uint256 r = ratio; uint256 msb; assembly { let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(5, gt(r, 0xFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(4, gt(r, 0xFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(3, gt(r, 0xFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(2, gt(r, 0xF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(1, gt(r, 0x3)) msb := or(msb, f) r := shr(f, r) } assembly { let f := gt(r, 0x1) msb := or(msb, f) } if (msb >= 128) r = ratio >> (msb - 127); else r = ratio << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= price ? tickHi : tickLow; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '../interfaces/IPeripheryPayments.sol'; import '../interfaces/external/IWNativeToken.sol'; import '../libraries/TransferHelper.sol'; import './PeripheryImmutableState.sol'; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState { receive() external payable { require(msg.sender == WNativeToken, 'Not WNativeToken'); } function _balanceOfToken(address token) private view returns (uint256) { return (IERC20(token).balanceOf(address(this))); } /// @inheritdoc IPeripheryPayments function unwrapWNativeToken(uint256 amountMinimum, address recipient) external payable override { uint256 balanceWNativeToken = _balanceOfToken(WNativeToken); require(balanceWNativeToken >= amountMinimum, 'Insufficient WNativeToken'); if (balanceWNativeToken > 0) { IWNativeToken(WNativeToken).withdraw(balanceWNativeToken); TransferHelper.safeTransferNative(recipient, balanceWNativeToken); } } /// @inheritdoc IPeripheryPayments function sweepToken(address token, uint256 amountMinimum, address recipient) external payable override { uint256 balanceToken = _balanceOfToken(token); require(balanceToken >= amountMinimum, 'Insufficient token'); if (balanceToken > 0) { TransferHelper.safeTransfer(token, recipient, balanceToken); } } /// @inheritdoc IPeripheryPayments function refundNativeToken() external payable override { if (address(this).balance > 0) TransferHelper.safeTransferNative(msg.sender, address(this).balance); } /// @param token The token to pay /// @param payer The entity that must pay /// @param recipient The entity that will receive payment /// @param value The amount to pay function pay(address token, address payer, address recipient, uint256 value) internal { if (token == WNativeToken && address(this).balance >= value) { // pay with WNativeToken // "address(this).balance >= value" may unexpectedly become false (including due to frontrun) // so this function should be accompanied by a `refundNativeToken` in multicall to avoid potential loss of tokens IWNativeToken(WNativeToken).deposit{value: value}(); // wrap only what is needed to pay IWNativeToken(WNativeToken).transfer(recipient, value); } else if (payer == address(this)) { // pay with tokens already in the contract (for the exact input multihop case) TransferHelper.safeTransfer(token, recipient, value); } else { // pull payment TransferHelper.safeTransferFrom(token, payer, recipient, value); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @title Interface for WNativeToken interface IWNativeToken is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.20; /// @notice A fork of Multicall2 specifically tailored for the Algebra Interface /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract AlgebraInterfaceMulticall { struct Call { address target; uint256 gasLimit; bytes callData; } struct Result { bool success; uint256 gasUsed; bytes returnData; } function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { timestamp = block.timestamp; } function getEthBalance(address addr) public view returns (uint256 balance) { balance = addr.balance; } function multicall(Call[] memory calls) public returns (uint256 blockNumber, Result[] memory returnData) { blockNumber = block.number; returnData = new Result[](calls.length); for (uint256 i = 0; i < calls.length; i++) { (address target, uint256 gasLimit, bytes memory callData) = ( calls[i].target, calls[i].gasLimit, calls[i].callData ); uint256 gasLeftBefore = gasleft(); (bool success, bytes memory ret) = target.call{gas: gasLimit}(callData); uint256 gasUsed = gasLeftBefore - gasleft(); returnData[i] = Result(success, gasUsed, ret); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/libraries/SafeCast.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickMath.sol'; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import './interfaces/ISwapRouter.sol'; import './base/PeripheryImmutableState.sol'; import './base/PeripheryValidation.sol'; import './base/PeripheryPaymentsWithFee.sol'; import './base/Multicall.sol'; import './base/SelfPermit.sol'; import './libraries/Path.sol'; import './libraries/PoolAddress.sol'; import './libraries/CallbackValidation.sol'; /// @title Algebra Integral 1.2.1 Swap Router /// @notice Router for stateless execution of swaps against Algebra /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract SwapRouter is ISwapRouter, PeripheryImmutableState, PeripheryValidation, PeripheryPaymentsWithFee, Multicall, SelfPermit { using Path for bytes; using SafeCast for uint256; /// @dev Used as the placeholder value for amountInCached, because the computed amount in for an exact output swap /// can never actually be this value uint256 private constant DEFAULT_AMOUNT_IN_CACHED = type(uint256).max; /// @dev Transient storage variable used for returning the computed amount in for an exact output swap. uint256 private amountInCached = DEFAULT_AMOUNT_IN_CACHED; constructor( address _factory, address _WNativeToken, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) {} /// @dev Returns the pool for the given token pair. The pool contract may or may not exist. function getPool(address deployer, address tokenA, address tokenB) private view returns (IAlgebraPool) { return IAlgebraPool(PoolAddress.computeAddress(poolDeployer, PoolAddress.getPoolKey(deployer, tokenA, tokenB))); } struct SwapCallbackData { bytes path; address payer; } /// @inheritdoc IAlgebraSwapCallback function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override { require(amount0Delta > 0 || amount1Delta > 0, 'Zero liquidity swap'); // swaps entirely within 0-liquidity regions are not supported SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData)); (address tokenIn, address deployer, address tokenOut) = data.path.decodeFirstPool(); CallbackValidation.verifyCallback(poolDeployer, deployer, tokenIn, tokenOut); (bool isExactInput, uint256 amountToPay) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta)) : (tokenOut < tokenIn, uint256(amount1Delta)); if (isExactInput) { pay(tokenIn, data.payer, msg.sender, amountToPay); } else { // either initiate the next swap or pay if (data.path.hasMultiplePools()) { data.path = data.path.skipToken(); exactOutputInternal(amountToPay, msg.sender, 0, data); } else { amountInCached = amountToPay; tokenIn = tokenOut; // swap in/out because exact output swaps are reversed pay(tokenIn, data.payer, msg.sender, amountToPay); } } } /// @dev Performs a single exact input swap function exactInputInternal( uint256 amountIn, address recipient, uint160 limitSqrtPrice, SwapCallbackData memory data ) private returns (uint256 amountOut) { if (recipient == address(0)) recipient = address(this); // allow swapping to the router address with address 0 (address tokenIn, address deployer, address tokenOut) = data.path.decodeFirstPool(); bool zeroToOne = tokenIn < tokenOut; (int256 amount0, int256 amount1) = getPool(deployer, tokenIn, tokenOut).swap( recipient, zeroToOne, amountIn.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encode(data) ); return uint256(-(zeroToOne ? amount1 : amount0)); } /// @inheritdoc ISwapRouter function exactInputSingle( ExactInputSingleParams calldata params ) external payable override checkDeadline(params.deadline) returns (uint256 amountOut) { amountOut = exactInputInternal( params.amountIn, params.recipient, params.limitSqrtPrice, SwapCallbackData({ path: abi.encodePacked(params.tokenIn, params.deployer, params.tokenOut), payer: msg.sender }) ); require(amountOut >= params.amountOutMinimum, 'Too little received'); } /// @inheritdoc ISwapRouter function exactInput( ExactInputParams memory params ) external payable override checkDeadline(params.deadline) returns (uint256 amountOut) { address payer = msg.sender; // msg.sender pays for the first hop while (true) { bool hasMultiplePools = params.path.hasMultiplePools(); // the outputs of prior swaps become the inputs to subsequent ones params.amountIn = exactInputInternal( params.amountIn, hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies 0, SwapCallbackData({ path: params.path.getFirstPool(), // only the first pool in the path is necessary payer: payer }) ); // decide whether to continue or terminate if (hasMultiplePools) { payer = address(this); // at this point, the caller has paid params.path = params.path.skipToken(); } else { amountOut = params.amountIn; break; } } require(amountOut >= params.amountOutMinimum, 'Too little received'); } /// @inheritdoc ISwapRouter function exactInputSingleSupportingFeeOnTransferTokens( ExactInputSingleParams calldata params ) external payable override checkDeadline(params.deadline) returns (uint256 amountOut) { SwapCallbackData memory data = SwapCallbackData({ path: abi.encodePacked(params.tokenIn, params.deployer, params.tokenOut), payer: msg.sender }); address recipient = params.recipient == address(0) ? address(this) : params.recipient; bool zeroToOne = params.tokenIn < params.tokenOut; (int256 amount0, int256 amount1) = getPool(params.deployer, params.tokenIn, params.tokenOut) .swapWithPaymentInAdvance( msg.sender, recipient, zeroToOne, params.amountIn.toInt256(), params.limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : params.limitSqrtPrice, abi.encode(data) ); amountOut = uint256(-(zeroToOne ? amount1 : amount0)); require(amountOut >= params.amountOutMinimum, 'Too little received'); } /// @dev Performs a single exact output swap function exactOutputInternal( uint256 amountOut, address recipient, uint160 limitSqrtPrice, SwapCallbackData memory data ) private returns (uint256 amountIn) { if (recipient == address(0)) recipient = address(this); // allow swapping to the router address with address 0 (address tokenOut, address deployer, address tokenIn) = data.path.decodeFirstPool(); bool zeroToOne = tokenIn < tokenOut; (int256 amount0Delta, int256 amount1Delta) = getPool(deployer, tokenIn, tokenOut).swap( recipient, zeroToOne, -amountOut.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encode(data) ); uint256 amountOutReceived; (amountIn, amountOutReceived) = zeroToOne ? (uint256(amount0Delta), uint256(-amount1Delta)) : (uint256(amount1Delta), uint256(-amount0Delta)); // it's technically possible to not receive the full output amount, // so if no price limit has been specified, require this possibility away if (limitSqrtPrice == 0) require(amountOutReceived == amountOut, 'Not received full amountOut'); } /// @inheritdoc ISwapRouter function exactOutputSingle( ExactOutputSingleParams calldata params ) external payable override checkDeadline(params.deadline) returns (uint256 amountIn) { // avoid an SLOAD by using the swap return data amountIn = exactOutputInternal( params.amountOut, params.recipient, params.limitSqrtPrice, SwapCallbackData({ path: abi.encodePacked(params.tokenOut, params.deployer, params.tokenIn), payer: msg.sender }) ); require(amountIn <= params.amountInMaximum, 'Too much requested'); amountInCached = DEFAULT_AMOUNT_IN_CACHED; // has to be reset even though we don't use it in the single hop case } /// @inheritdoc ISwapRouter function exactOutput( ExactOutputParams calldata params ) external payable override checkDeadline(params.deadline) returns (uint256 amountIn) { // it's okay that the payer is fixed to msg.sender here, as they're only paying for the "final" exact output // swap, which happens first, and subsequent swaps are paid for within nested callback frames exactOutputInternal( params.amountOut, params.recipient, 0, SwapCallbackData({path: params.path, payer: msg.sender}) ); amountIn = amountInCached; require(amountIn <= params.amountInMaximum, 'Too much requested'); amountInCached = DEFAULT_AMOUNT_IN_CACHED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; import '../libraries/LiquidityAmounts.sol'; contract LiquidityAmountsTest { function getLiquidityForAmount0( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0 ) external pure returns (uint128 liquidity) { return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0); } function getGasCostOfGetLiquidityForAmount0( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0 ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0); return gasBefore - gasleft(); } function getLiquidityForAmount1( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1 ) external pure returns (uint128 liquidity) { return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1); } function getGasCostOfGetLiquidityForAmount1( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1 ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1); return gasBefore - gasleft(); } function getLiquidityForAmounts( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0, uint256 amount1 ) external pure returns (uint128 liquidity) { return LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1); } function getGasCostOfGetLiquidityForAmounts( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0, uint256 amount1 ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1); return gasBefore - gasleft(); } function getAmount0ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external pure returns (uint256 amount0) { return LiquidityAmounts.getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity); } function getGasCostOfGetAmount0ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity); return gasBefore - gasleft(); } function getAmount1ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external pure returns (uint256 amount1) { return LiquidityAmounts.getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity); } function getGasCostOfGetAmount1ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, liquidity); return gasBefore - gasleft(); } function getAmountsForLiquidity( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external pure returns (uint256 amount0, uint256 amount1) { return LiquidityAmounts.getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity); } function getGasCostOfGetAmountsForLiquidity( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) external view returns (uint256) { uint256 gasBefore = gasleft(); LiquidityAmounts.getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity); return gasBefore - gasleft(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/integral-core/contracts/libraries/TickTree.sol'; import '../interfaces/ITickLens.sol'; /// @title Algebra Integral 1.2.1 Tick Lens contract /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract TickLens is ITickLens { /// @inheritdoc ITickLens function getPopulatedTicksInWord( address pool, int16 tickTableIndex ) public view override returns (PopulatedTick[] memory populatedTicks) { // fetch bitmap uint256 bitmap = IAlgebraPool(pool).tickTable(tickTableIndex); unchecked { // calculate the number of populated ticks uint256 numberOfPopulatedTicks; for (uint256 i = 0; i < 256; i++) { if (bitmap & (1 << i) > 0) numberOfPopulatedTicks++; } // fetch populated tick data populatedTicks = new PopulatedTick[](numberOfPopulatedTicks); for (uint256 i = 0; i < 256; i++) { if (bitmap & (1 << i) > 0) { int24 populatedTick = ((int24(tickTableIndex) << 8) + int24(uint24(i))); (uint256 liquidityGross, int128 liquidityNet, , ) = _getTick(pool, populatedTick); populatedTicks[--numberOfPopulatedTicks] = PopulatedTick({ tick: populatedTick, liquidityNet: liquidityNet, liquidityGross: uint128(liquidityGross) }); } } } } /// @inheritdoc ITickLens function getClosestActiveTicks( address pool, int24 targetTick ) public view override returns (PopulatedTick[2] memory populatedTicks) { uint32 tickTreeRoot = IAlgebraPool(pool).tickTreeRoot(); uint16 rootIndex = uint16(uint24((int24(targetTick >> 8) + TickTree.SECOND_LAYER_OFFSET) >> 8)); int24 activeTickIndex; bool initialized; if ((1 << rootIndex) & tickTreeRoot != 0) { uint256 leafNode = _fetchBitmap(pool, int16(targetTick >> 8)); (activeTickIndex, initialized) = TickTree._nextActiveBitInWord(leafNode, targetTick); if (!initialized) { int16 secondLayerIndex = int16((targetTick >> 8) + int24(TickTree.SECOND_LAYER_OFFSET) + 1); uint256 secondLayerNode = _fetchSecondLayerNode(pool, secondLayerIndex >> 8); (int24 activeLeafIndex, bool initializedSecondLayer) = TickTree._nextActiveBitInWord( secondLayerNode, secondLayerIndex ); if (initializedSecondLayer) { int24 nextTickIndex = int24(activeLeafIndex - TickTree.SECOND_LAYER_OFFSET) << 8; leafNode = _fetchBitmap(pool, int16(activeLeafIndex - TickTree.SECOND_LAYER_OFFSET)); (activeTickIndex, initialized) = TickTree._nextActiveBitInWord(leafNode, nextTickIndex); } else { rootIndex++; } } } if (!initialized) { (int24 nextActiveSecondLayerNode, ) = TickTree._nextActiveBitInWord(tickTreeRoot, int16(rootIndex)); uint256 secondLayerNode = _fetchSecondLayerNode(pool, int16(nextActiveSecondLayerNode)); (int24 activeLeafIndex, bool initializedSecondLayer) = TickTree._nextActiveBitInWord( secondLayerNode, int24(nextActiveSecondLayerNode) << 8 ); if (initializedSecondLayer) { uint256 leafNode = _fetchBitmap(pool, int16(activeLeafIndex - TickTree.SECOND_LAYER_OFFSET)); (activeTickIndex, ) = TickTree._nextActiveBitInWord( leafNode, int24(activeLeafIndex - TickTree.SECOND_LAYER_OFFSET) << 8 ); } else { activeTickIndex = TickMath.MAX_TICK; } } if (activeTickIndex == targetTick) { (uint256 liquidityGross, int128 liquidityNet, , int24 nextTick) = _getTick(pool, targetTick); populatedTicks[0] = PopulatedTick({ tick: targetTick, liquidityNet: liquidityNet, liquidityGross: uint128(liquidityGross) }); (liquidityGross, liquidityNet, , ) = _getTick(pool, nextTick); populatedTicks[1] = PopulatedTick({ tick: nextTick, liquidityNet: liquidityNet, liquidityGross: uint128(liquidityGross) }); } else { (uint256 liquidityGross, int128 liquidityNet, int24 previousTick, ) = _getTick(pool, activeTickIndex); populatedTicks[1] = PopulatedTick({ tick: activeTickIndex, liquidityNet: liquidityNet, liquidityGross: uint128(liquidityGross) }); (liquidityGross, liquidityNet, , ) = _getTick(pool, previousTick); populatedTicks[0] = PopulatedTick({ tick: previousTick, liquidityNet: liquidityNet, liquidityGross: uint128(liquidityGross) }); } } /// @inheritdoc ITickLens function getNextActiveTicks( address pool, int24 startingTick, uint256 amount, bool upperDirection ) public view override returns (PopulatedTick[] memory populatedTicks) { int24 currentTick = startingTick; // prevent pointers from being initialized // if we initialize the populatedTicks array directly, it will automatically write `amount` pointers to structs in array bytes32[] memory populatedTicksPointers = new bytes32[](amount); assembly { populatedTicks := populatedTicksPointers } (uint256 liquidityGross, int128 liquidityNet, int24 previousTick, int24 nextTick, , ) = IAlgebraPool(pool) .ticks(currentTick); require(previousTick != nextTick, 'Invalid startingTick'); bytes32 freeMemoryPointer; assembly { freeMemoryPointer := mload(0x40) } unchecked { for (uint256 i; i < amount; ++i) { // allocate memory for new struct and set it without rewriting free memory pointer assembly { mstore(freeMemoryPointer, currentTick) mstore(add(freeMemoryPointer, 0x20), liquidityNet) mstore(add(freeMemoryPointer, 0x40), liquidityGross) } // prevent array length check and store new pointer in array assembly { mstore(add(mul(i, 0x20), add(populatedTicks, 0x20)), freeMemoryPointer) freeMemoryPointer := add(freeMemoryPointer, 0x60) } int24 newCurrentTick = upperDirection ? nextTick : previousTick; if (newCurrentTick == currentTick) { // reached MAX or MIN tick assembly { mstore(populatedTicks, add(i, 1)) // cap returning array length } break; } currentTick = newCurrentTick; (liquidityGross, liquidityNet, previousTick, nextTick) = _getTick(pool, currentTick); } } assembly { mstore(0x40, freeMemoryPointer) // rewrite free memory pointer slot } } // prevents memory expansion during staticcall // will use [0x00, 0xC0] memory slots function _getTick( address pool, int24 index ) internal view virtual returns (uint128 liquidityGross, int128 liquidityNet, int24 previousTick, int24 nextTick) { assembly { let freeMemoryPointer := mload(0x40) // we will need to restore memory further let slot1 := mload(0x60) let slot2 := mload(0x80) let slot3 := mload(0xA0) mstore(0x00, 0xf30dba9300000000000000000000000000000000000000000000000000000000) // "ticks" selector mstore(0x04, index) let success := staticcall(gas(), pool, 0, 0x24, 0, 0xC0) liquidityGross := mload(0) liquidityNet := mload(0x20) previousTick := mload(0x40) nextTick := mload(0x60) mstore(0x40, freeMemoryPointer) // restore memory mstore(0x60, slot1) mstore(0x80, slot2) mstore(0xA0, slot3) } } function _fetchBitmap(address pool, int16 index) internal view virtual returns (uint256 word) { assembly { mstore(0x00, 0xc677e3e000000000000000000000000000000000000000000000000000000000) // "tickTable(int16)" selector mstore(0x04, index) let success := staticcall(gas(), pool, 0, 0x24, 0, 0x20) word := mload(0) } } function _fetchSecondLayerNode(address pool, int16 index) internal view virtual returns (uint256 word) { assembly { mstore(0x00, 0xd861903700000000000000000000000000000000000000000000000000000000) // "tickTreeSecondLayer(int16)" selector mstore(0x04, index) let success := staticcall(gas(), pool, 0, 0x24, 0, 0x20) word := mload(0) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.20; pragma abicoder v2; import '../base/Multicall.sol'; contract TestMulticall is Multicall { error CustomError(); function functionThatRevertsWithError(string memory error) external pure { revert(error); } function functionThatRevertsSilently() external pure { revert(); } function functionThatRevertsWithCustomError() external pure { revert CustomError(); } function functionThatRevertsWithPanic() external pure returns (uint256) { uint256 a = 5; return a - 10; } struct Tuple { uint256 a; uint256 b; } function functionThatReturnsTuple(uint256 a, uint256 b) external pure returns (Tuple memory tuple) { tuple = Tuple({b: a, a: b}); } uint256 public paid; function pays() external payable { paid += msg.value; } function returnSender() external view returns (address) { return msg.sender; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; /// @title Optimized overflow and underflow safe math operations /// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library LowGasSafeMath { /// @notice Returns x + y, reverts if sum overflows uint256 /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { require((z = x + y) >= x); } } /// @notice Returns x - y, reverts if underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { require((z = x - y) <= x); } } /// @notice Returns x * y, reverts if overflows /// @param x The multiplicand /// @param y The multiplier /// @return z The product of x and y function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { require(x == 0 || (z = x * y) / x == y); } } /// @notice Returns x + y, reverts if overflows or underflows /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(int256 x, int256 y) internal pure returns (int256 z) { unchecked { require((z = x + y) >= x == (y >= 0)); } } /// @notice Returns x - y, reverts if overflows or underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(int256 x, int256 y) internal pure returns (int256 z) { unchecked { require((z = x - y) <= x == (y >= 0)); } } /// @notice Returns x + y, reverts if overflows or underflows /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add128(uint128 x, uint128 y) internal pure returns (uint128 z) { unchecked { require((z = x + y) >= x); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import './INonfungiblePositionManager.sol'; /// @title Describes position NFT tokens via URI /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface INonfungibleTokenPositionDescriptor { /// @notice Produces the URI describing a particular token ID for a position manager /// @dev Note this URI may be a data: URI with the JSON contents directly inlined /// @param positionManager The position manager for which to describe the token /// @param tokenId The ID of the token for which to produce a description, which may not be valid /// @return The URI of the ERC721-compliant metadata function tokenURI(INonfungiblePositionManager positionManager, uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '@cryptoalgebra/integral-core/contracts/interfaces/IAlgebraPool.sol'; /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolTicksCounter { /// @dev This function counts the number of initialized ticks that would incur a gas cost between tickBefore and tickAfter. /// When tickBefore and/or tickAfter themselves are initialized, the logic over whether we should count them depends on the /// direction of the swap. If we are swapping upwards (tickAfter > tickBefore) we don't want to count tickBefore but we do /// want to count tickAfter. The opposite is true if we are swapping downwards. function countInitializedTicksCrossed( IAlgebraPool self, int24 tickBefore, int24 tickAfter ) internal view returns (uint32 initializedTicksCrossed) { int16 wordPosLower; int16 wordPosHigher; uint8 bitPosLower; uint8 bitPosHigher; bool tickBeforeInitialized; bool tickAfterInitialized; { // Get the key and offset in the tick bitmap of the active tick before and after the swap. int16 wordPos = int16(tickBefore >> 8); uint8 bitPos = uint8(int8(tickBefore % 256)); int16 wordPosAfter = int16(tickAfter >> 8); uint8 bitPosAfter = uint8(int8(tickAfter % 256)); // In the case where tickAfter is initialized, we only want to count it if we are swapping downwards. // If the initializable tick after the swap is initialized, our original tickAfter is a // multiple of tick spacing, and we are swapping downwards we know that tickAfter is initialized // and we shouldn't count it. tickAfterInitialized = ((self.tickTable(wordPosAfter) & (1 << bitPosAfter)) > 0) && ((tickAfter % self.tickSpacing()) == 0) && (tickBefore > tickAfter); // In the case where tickBefore is initialized, we only want to count it if we are swapping upwards. // Use the same logic as above to decide whether we should count tickBefore or not. tickBeforeInitialized = ((self.tickTable(wordPos) & (1 << bitPos)) > 0) && ((tickBefore % self.tickSpacing()) == 0) && (tickBefore < tickAfter); if (wordPos < wordPosAfter || (wordPos == wordPosAfter && bitPos <= bitPosAfter)) { wordPosLower = wordPos; bitPosLower = bitPos; wordPosHigher = wordPosAfter; bitPosHigher = bitPosAfter; } else { wordPosLower = wordPosAfter; bitPosLower = bitPosAfter; wordPosHigher = wordPos; bitPosHigher = bitPos; } } // Count the number of initialized ticks crossed by iterating through the tick bitmap. // Our first mask should include the lower tick and everything to its left. uint256 mask = type(uint256).max << bitPosLower; while (wordPosLower <= wordPosHigher) { // If we're on the final tick bitmap page, ensure we only count up to our // ending tick. if (wordPosLower == wordPosHigher) { mask = mask & (type(uint256).max >> (255 - bitPosHigher)); } uint256 masked = self.tickTable(wordPosLower) & mask; initializedTicksCrossed += countOneBits(masked); wordPosLower++; // Reset our mask so we consider all bits on the next iteration. mask = type(uint256).max; } if (tickAfterInitialized) { initializedTicksCrossed -= 1; } if (tickBeforeInitialized) { initializedTicksCrossed -= 1; } return initializedTicksCrossed; } function countOneBits(uint256 x) private pure returns (uint16) { uint16 bits = 0; while (x != 0) { bits++; x &= (x - 1); } return bits; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import './SafeCast.sol'; import './FullMath.sol'; import './Constants.sol'; /// @title Functions based on Q64.96 sqrt price and liquidity /// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas library TokenDeltaMath { using SafeCast for uint256; /// @notice Gets the token0 delta between two prices /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper) /// @param priceLower A Q64.96 sqrt price /// @param priceUpper Another Q64.96 sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up or down /// @return token0Delta Amount of token0 required to cover a position of size liquidity between the two passed prices function getToken0Delta(uint160 priceLower, uint160 priceUpper, uint128 liquidity, bool roundUp) internal pure returns (uint256 token0Delta) { unchecked { uint256 priceDelta = priceUpper - priceLower; require(priceDelta < priceUpper); // forbids underflow and 0 priceLower uint256 liquidityShifted = uint256(liquidity) << Constants.RESOLUTION; token0Delta = roundUp ? FullMath.unsafeDivRoundingUp(FullMath.mulDivRoundingUp(priceDelta, liquidityShifted, priceUpper), priceLower) // denominator always > 0 : FullMath.mulDiv(priceDelta, liquidityShifted, priceUpper) / priceLower; } } /// @notice Gets the token1 delta between two prices /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower)) /// @param priceLower A Q64.96 sqrt price /// @param priceUpper Another Q64.96 sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up, or down /// @return token1Delta Amount of token1 required to cover a position of size liquidity between the two passed prices function getToken1Delta(uint160 priceLower, uint160 priceUpper, uint128 liquidity, bool roundUp) internal pure returns (uint256 token1Delta) { unchecked { require(priceUpper >= priceLower); uint256 priceDelta = priceUpper - priceLower; token1Delta = roundUp ? FullMath.mulDivRoundingUp(priceDelta, liquidity, Constants.Q96) : FullMath.mulDiv(priceDelta, liquidity, Constants.Q96); } } /// @notice Helper that gets signed token0 delta /// @param priceLower A Q64.96 sqrt price /// @param priceUpper Another Q64.96 sqrt price /// @param liquidity The change in liquidity for which to compute the token0 delta /// @return token0Delta Amount of token0 corresponding to the passed liquidityDelta between the two prices function getToken0Delta(uint160 priceLower, uint160 priceUpper, int128 liquidity) internal pure returns (int256 token0Delta) { unchecked { token0Delta = liquidity >= 0 ? getToken0Delta(priceLower, priceUpper, uint128(liquidity), true).toInt256() : -getToken0Delta(priceLower, priceUpper, uint128(-liquidity), false).toInt256(); } } /// @notice Helper that gets signed token1 delta /// @param priceLower A Q64.96 sqrt price /// @param priceUpper Another Q64.96 sqrt price /// @param liquidity The change in liquidity for which to compute the token1 delta /// @return token1Delta Amount of token1 corresponding to the passed liquidityDelta between the two prices function getToken1Delta(uint160 priceLower, uint160 priceUpper, int128 liquidity) internal pure returns (int256 token1Delta) { unchecked { token1Delta = liquidity >= 0 ? getToken1Delta(priceLower, priceUpper, uint128(liquidity), true).toInt256() : -getToken1Delta(priceLower, priceUpper, uint128(-liquidity), false).toInt256(); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Interface for permit /// @notice Interface used by DAI/CHAI for permit interface IERC20PermitAllowed { /// @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` function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// 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 offset of a custom pool deployer address uint256 private constant DEPLOYER_OFFSET = ADDR_SIZE; /// @dev The offset of a single token address + deployer address uint256 private constant NEXT_OFFSET = ADDR_SIZE + DEPLOYER_OFFSET; /// @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 if 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 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 deployer The address of the custom pool deployer /// @return tokenB The second token of the given pool function decodeFirstPool( bytes memory path ) internal pure returns (address tokenA, address deployer, address tokenB) { tokenA = path.toAddress(0); deployer = path.toAddress(DEPLOYER_OFFSET); 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); } /// @notice Skips a token element from the buffer and returns the remainder /// @param path The swap path /// @return The remaining token 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: UNLICENSED pragma solidity =0.8.20; import '../interfaces/external/IERC1271.sol'; contract TestPositionNFTOwner is IERC1271 { address public owner; function setOwner(address _owner) external { owner = _owner; } function isValidSignature(bytes32 hash, bytes memory signature) external view override returns (bytes4 magicValue) { bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } if (ecrecover(hash, v, r, s) == owner) { return bytes4(0x1626ba7e); } else { return bytes4(0); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.20; import '@cryptoalgebra/integral-core/contracts/interfaces/plugin/IAlgebraPlugin.sol'; contract MockPlugin is IAlgebraPlugin { function defaultPluginConfig() external pure returns (uint8) { return 0; } function beforeInitialize(address, uint160) external pure returns (bytes4) { return IAlgebraPlugin.beforeInitialize.selector; } function afterInitialize(address, uint160, int24) external pure returns (bytes4) { return IAlgebraPlugin.afterInitialize.selector; } function beforeModifyPosition( address, address, int24, int24, int128, bytes calldata ) external pure returns (bytes4, uint24) { return (IAlgebraPlugin.beforeModifyPosition.selector, 0); } function handlePluginFee(uint256, uint256) external pure returns (bytes4) { return IAlgebraPlugin.handlePluginFee.selector; } function afterModifyPosition( address, address, int24, int24, int128, uint256, uint256, bytes calldata ) external pure returns (bytes4) { return IAlgebraPlugin.afterModifyPosition.selector; } function beforeSwap(address, address, bool, int256, uint160, bool, bytes calldata) external pure returns (bytes4, uint24, uint24) { return (IAlgebraPlugin.beforeSwap.selector, 0, 0); } function afterSwap( address, address, bool, int256, uint160, int256, int256, bytes calldata ) external pure returns (bytes4) { return IAlgebraPlugin.afterSwap.selector; } function beforeFlash(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { return IAlgebraPlugin.beforeFlash.selector; } function afterFlash( address, address, uint256, uint256, uint256, uint256, bytes calldata ) external pure returns (bytes4) { return IAlgebraPlugin.afterFlash.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev See {ERC721-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); if (batchSize > 1) { // Will only trigger during construction. Batch transferring (minting) is not available afterwards. revert("ERC721Enumerable: consecutive transfers not supported"); } uint256 tokenId = firstTokenId; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import './IMulticall.sol'; import './ISelfPermit.sol'; import './IPoolInitializer.sol'; /// @title Algebra Migrator /// @notice Enables migration of liquidity from Uniswap v2-compatible pairs into Algebra pools /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IV3Migrator is IMulticall, ISelfPermit, IPoolInitializer { struct MigrateParams { address pair; // the Uniswap v2-compatible pair uint256 liquidityToMigrate; // expected to be balanceOf(msg.sender) uint8 percentageToMigrate; // represented as a numerator over 100 address token0; address token1; address deployer; int24 tickLower; int24 tickUpper; uint256 amount0Min; // must be discounted by percentageToMigrate uint256 amount1Min; // must be discounted by percentageToMigrate address recipient; uint256 deadline; bool refundAsNative; } /// @notice Migrates liquidity to Algebra by burning v2 liquidity and minting a new position for Algebra /// @dev Slippage protection is enforced via `amount{0,1}Min`, which should be a discount of the expected values of /// the maximum amount of Algebra liquidity that the v2 liquidity can get. For the special case of migrating to an /// out-of-range position, `amount{0,1}Min` may be set to 0, enforcing that the position remains out of range /// @param params The params necessary to migrate v2 liquidity, encoded as `MigrateParams` in calldata function migrate(MigrateParams calldata params) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; library AddressStringUtil { // converts an address to the uppercase hex string, extracting only len bytes (up to 20, multiple of 2) function toAsciiString(address addr, uint256 len) internal pure returns (string memory) { unchecked { require(len % 2 == 0 && len > 0 && len <= 40, 'AddressStringUtil: INVALID_LEN'); bytes memory s = new bytes(len); uint256 addrNum = uint256(uint160(addr)); for (uint256 i = 0; i < len / 2; i++) { // shift right and truncate all but the least significant byte to extract the byte at position 19-i uint8 b = uint8(addrNum >> (8 * (19 - i))); // first hex character is the most significant 4 bits uint8 hi = b >> 4; // second hex character is the least significant 4 bits uint8 lo = b - (hi << 4); s[2 * i] = char(hi); s[2 * i + 1] = char(lo); } return string(s); } } // hi and lo are only 4 bits and between 0 and 16 // this method converts those values to the unicode/ascii code point for the hex representation // uses upper case for the characters function char(uint8 b) private pure returns (bytes1 c) { unchecked { if (b < 10) { return bytes1(b + 0x30); } else { return bytes1(b + 0x37); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^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}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 1000000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
0x6080604052604051620010c7380380620010c7833981016040819052620000269162000424565b828162000036828260006200004d565b50620000449050826200007f565b50505062000557565b6200005883620000f1565b600082511180620000665750805b156200007a5762000078838362000133565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000c160008051602062001080833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000ee8162000162565b50565b620000fc8162000200565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200015b8383604051806060016040528060278152602001620010a06027913962000297565b9392505050565b6001600160a01b038116620001cd5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80600080516020620010808339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b6200026f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001c4565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc620001df565b6060600080856001600160a01b031685604051620002b6919062000504565b600060405180830381855af49150503d8060008114620002f3576040519150601f19603f3d011682016040523d82523d6000602084013e620002f8565b606091505b5090925090506200030c8683838762000316565b9695505050505050565b606083156200038a57825160000362000382576001600160a01b0385163b620003825760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001c4565b508162000396565b6200039683836200039e565b949350505050565b815115620003af5781518083602001fd5b8060405162461bcd60e51b8152600401620001c4919062000522565b80516001600160a01b0381168114620003e357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200041b57818101518382015260200162000401565b50506000910152565b6000806000606084860312156200043a57600080fd5b6200044584620003cb565b92506200045560208501620003cb565b60408501519092506001600160401b03808211156200047357600080fd5b818601915086601f8301126200048857600080fd5b8151818111156200049d576200049d620003e8565b604051601f8201601f19908116603f01168101908382118183101715620004c857620004c8620003e8565b81604052828152896020848701011115620004e257600080fd5b620004f5836020830160208801620003fe565b80955050505050509250925092565b6000825162000518818460208701620003fe565b9190910192915050565b602081526000825180602084015262000543816040850160208701620003fe565b601f01601f19169190910160400192915050565b610b1980620005676000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6102a1565b73ffffffffffffffffffffffffffffffffffffffff1633036102975760607fffffffff00000000000000000000000000000000000000000000000000000000600035167fc9a6301a000000000000000000000000000000000000000000000000000000008101610098576100916102e1565b915061028f565b7fb0e10d7a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016100e957610091610338565b7f70d7c690000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161013a5761009161037e565b7f07ae5bc0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161018b576100916103af565b7fa39f25e5000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016101dc576100916103fc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b815160208301f35b61029f610410565b565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b60606102eb610420565b60006102fa36600481846108d7565b810190610307919061092a565b90506103248160405180602001604052806000815250600061042b565b505060408051602081019091526000815290565b606060008061034a36600481846108d7565b8101906103579190610974565b915091506103678282600161042b565b604051806020016040528060008152509250505090565b6060610388610420565b600061039736600481846108d7565b8101906103a4919061092a565b905061032481610457565b60606103b9610420565b60006103c36102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff831660208201529192500160405160208183030381529060405291505090565b6060610406610420565b60006103c36104bb565b61029f61041b6104bb565b6104ca565b341561029f57600080fd5b610434836104ee565b6000825111806104415750805b1561045257610450838361053b565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104806102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16104b881610567565b50565b60006104c5610673565b905090565b3660008037600080366000845af43d6000803e8080156104e9573d6000f35b3d6000fd5b6104f78161069b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606105608383604051806060016040528060278152602001610ae660279139610766565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661060a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610286565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6102c5565b73ffffffffffffffffffffffffffffffffffffffff81163b61073f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610286565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61062d565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516107909190610a78565b600060405180830381855af49150503d80600081146107cb576040519150601f19603f3d011682016040523d82523d6000602084013e6107d0565b606091505b50915091506107e1868383876107eb565b9695505050505050565b6060831561088157825160000361087a5773ffffffffffffffffffffffffffffffffffffffff85163b61087a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610286565b508161088b565b61088b8383610893565b949350505050565b8151156108a35781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102869190610a94565b600080858511156108e757600080fd5b838611156108f457600080fd5b5050820193919092039150565b803573ffffffffffffffffffffffffffffffffffffffff8116811461092557600080fd5b919050565b60006020828403121561093c57600080fd5b61056082610901565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561098757600080fd5b61099083610901565b9150602083013567ffffffffffffffff808211156109ad57600080fd5b818501915085601f8301126109c157600080fd5b8135818111156109d3576109d3610945565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610a1957610a19610945565b81604052828152886020848701011115610a3257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b83811015610a6f578181015183820152602001610a57565b50506000910152565b60008251610a8a818460208701610a54565b9190910192915050565b6020815260008251806020840152610ab3816040850160208701610a54565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000814000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564000000000000000000000000d637cbc214bc3dd354abb309f4fe717ffdd0b28c000000000000000000000000dead1f5af792afc125812e875a891b038f88825800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040523661001357610011610017565b005b6100115b61001f6102a1565b73ffffffffffffffffffffffffffffffffffffffff1633036102975760607fffffffff00000000000000000000000000000000000000000000000000000000600035167fc9a6301a000000000000000000000000000000000000000000000000000000008101610098576100916102e1565b915061028f565b7fb0e10d7a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016100e957610091610338565b7f70d7c690000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161013a5761009161037e565b7f07ae5bc0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161018b576100916103af565b7fa39f25e5000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016101dc576100916103fc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b815160208301f35b61029f610410565b565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b60606102eb610420565b60006102fa36600481846108d7565b810190610307919061092a565b90506103248160405180602001604052806000815250600061042b565b505060408051602081019091526000815290565b606060008061034a36600481846108d7565b8101906103579190610974565b915091506103678282600161042b565b604051806020016040528060008152509250505090565b6060610388610420565b600061039736600481846108d7565b8101906103a4919061092a565b905061032481610457565b60606103b9610420565b60006103c36102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff831660208201529192500160405160208183030381529060405291505090565b6060610406610420565b60006103c36104bb565b61029f61041b6104bb565b6104ca565b341561029f57600080fd5b610434836104ee565b6000825111806104415750805b1561045257610450838361053b565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104806102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16104b881610567565b50565b60006104c5610673565b905090565b3660008037600080366000845af43d6000803e8080156104e9573d6000f35b3d6000fd5b6104f78161069b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606105608383604051806060016040528060278152602001610ae660279139610766565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661060a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610286565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6102c5565b73ffffffffffffffffffffffffffffffffffffffff81163b61073f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610286565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61062d565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516107909190610a78565b600060405180830381855af49150503d80600081146107cb576040519150601f19603f3d011682016040523d82523d6000602084013e6107d0565b606091505b50915091506107e1868383876107eb565b9695505050505050565b6060831561088157825160000361087a5773ffffffffffffffffffffffffffffffffffffffff85163b61087a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610286565b508161088b565b61088b8383610893565b949350505050565b8151156108a35781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102869190610a94565b600080858511156108e757600080fd5b838611156108f457600080fd5b5050820193919092039150565b803573ffffffffffffffffffffffffffffffffffffffff8116811461092557600080fd5b919050565b60006020828403121561093c57600080fd5b61056082610901565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561098757600080fd5b61099083610901565b9150602083013567ffffffffffffffff808211156109ad57600080fd5b818501915085601f8301126109c157600080fd5b8135818111156109d3576109d3610945565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610a1957610a19610945565b81604052828152886020848701011115610a3257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b83811015610a6f578181015183820152602001610a57565b50506000910152565b60008251610a8a818460208701610a54565b9190910192915050565b6020815260008251806020840152610ab3816040850160208701610a54565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000814000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.