Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Name:
UniV3Adapter2
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; import "../interfaces/IAdapter.sol"; import "../interfaces/IUniswapV3SwapCallback.sol"; import "../interfaces/IUniV3.sol"; import "../interfaces/IERC20.sol"; import "../libraries/UniversalERC20.sol"; import "../libraries/SafeERC20.sol"; import "../libraries/TickMath.sol"; import "../interfaces/IWETH.sol"; /// @title UniV3Adapter /// @notice Explain to an end user what this does /// @dev Explain to a developer any extra details contract UniV3Adapter2 is IAdapter, IUniswapV3SwapCallback { address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; uint256 internal constant ORIGIN_PAYER = 0x3ca20afc2ccc0000000000000000000000000000000000000000000000000000; address public immutable WETH; constructor(address payable weth) { WETH = weth; } function _uniV3Swap( address to, address pool, uint160 sqrtX96, bytes memory data, uint256 payerOrigin ) internal { address _payerOrigin; if ((payerOrigin & ORIGIN_PAYER) == ORIGIN_PAYER) { _payerOrigin = address(uint160(uint256(payerOrigin))); } (address fromToken, address toToken, ) = abi.decode( data, (address, address, uint24) ); uint256 sellAmount = IERC20(fromToken).balanceOf(address(this)); bool zeroForOne = fromToken < toToken; IUniV3(pool).swap( to, zeroForOne, int256(sellAmount), sqrtX96 == 0 ? ( zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1 ) : sqrtX96, data ); uint amount = IERC20(fromToken).balanceOf(address(this)); if (amount > 0 && _payerOrigin != address(0)) { IERC20(fromToken).transfer(_payerOrigin, amount); } } function sellBase( address to, address pool, bytes memory moreInfo ) external override { (uint160 sqrtX96, bytes memory data) = abi.decode( moreInfo, (uint160, bytes) ); uint256 payerOrigin; assembly { let size := calldatasize() payerOrigin := calldataload(sub(size, 32)) } _uniV3Swap(to, pool, sqrtX96, data, payerOrigin); } function sellQuote( address to, address pool, bytes memory moreInfo ) external override { (uint160 sqrtX96, bytes memory data) = abi.decode( moreInfo, (uint160, bytes) ); uint256 payerOrigin; assembly { let size := calldatasize() payerOrigin := calldataload(sub(size, 32)) } _uniV3Swap(to, pool, sqrtX96, data, payerOrigin); } // for uniV3 callback function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata _data ) external override { require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported (address tokenIn, address tokenOut, ) = abi.decode( _data, (address, address, uint24) ); (bool isExactInput, uint256 amountToPay) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta)) : (tokenOut < tokenIn, uint256(amount1Delta)); if (isExactInput) { pay(tokenIn, address(this), msg.sender, amountToPay); } else { tokenIn = tokenOut; // swap in/out because exact output swaps are reversed pay(tokenIn, address(this), msg.sender, amountToPay); } } /// @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 == WETH && address(this).balance >= value) { // pay with WETH9 IWETH(WETH).deposit{value: value}(); // wrap only what is needed to pay IWETH(WETH).transfer(recipient, value); } else if (payer == address(this)) { // pay with tokens already in the contract (for the exact input multihop case) SafeERC20.safeTransfer(IERC20(token), recipient, value); } else { // pull payment SafeERC20.safeTransferFrom(IERC20(token), payer, recipient, value); } } }
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; interface IAdapter { function sellBase( address to, address pool, bytes memory data ) external; function sellQuote( address to, address pool, bytes memory data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Interface for DAI-style permits interface IDaiLikePermit { function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { event Approval( address indexed owner, address indexed spender, uint256 value ); event Transfer(address indexed from, address indexed to, uint256 value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#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 UniswapV3Pool deployed by the canonical UniswapV3Factory. /// 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 IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; interface IUniV3 { function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external returns (int256 amount0, int256 amount1); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function token0() external view returns (address); function token1() external view returns (address); /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6 /// @return The fee function fee() external view returns (uint24); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; interface IWETH { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address src, address dst, uint256 wad ) external returns (bool); function deposit() external payable; function withdraw(uint256 wad) external; }
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return payable(account); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } }
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library RevertReasonForwarder { function reRevert() internal pure { // bubble up revert reason from latest external call /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } }
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./SafeMath.sol"; import "./Address.sol"; import "./RevertReasonForwarder.sol"; import "../interfaces/IERC20.sol"; import "../interfaces/IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; // File @1inch/solidity-utils/contracts/libraries/[email protected] library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); // Ensures method do not revert or return boolean `true`, admits call to non-smart-contract function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { bytes4 selector = token.transferFrom.selector; bool success; /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } // Ensures method do not revert or return boolean `true`, admits call to non-smart-contract function safeTransfer(IERC20 token, address to, uint256 value) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } function safeApprove(IERC20 token, address spender, uint256 value) internal { forceApprove(token, spender, value); } // If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry function forceApprove(IERC20 token, address spender, uint256 value) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if (!_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value)) { revert ForceApproveFailed(); } } } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } function safePermit(IERC20 token, bytes calldata permit) internal { bool success; if (permit.length == 32 * 7) { success = _makeCalldataCall(token, IERC20Permit.permit.selector, permit); } else if (permit.length == 32 * 8) { success = _makeCalldataCall(token, IDaiLikePermit.permit.selector, permit); } else { revert SafePermitBadLength(); } if (!success) RevertReasonForwarder.reRevert(); } function _makeCall(IERC20 token, bytes4 selector, address to, uint256 amount) private returns(bool success) { /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } function _makeCalldataCall(IERC20 token, bytes4 selector, bytes calldata args) private returns(bool success) { /// @solidity memory-safe-assembly assembly { // solhint-disable-line no-inline-assembly let len := add(4, args.length) let data := mload(0x40) mstore(data, selector) calldatacopy(add(data, 0x04), args.offset, args.length) success := call(gas(), token, 0, data, len, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library SafeMath { uint256 constant WAD = 10**18; uint256 constant RAY = 10**27; function wad() public pure returns (uint256) { return WAD; } function ray() public pure returns (uint256) { return RAY; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a <= b ? a : b; } function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function sqrt(uint256 a) internal pure returns (uint256 b) { if (a > 3) { b = a; uint256 x = a / 2 + 1; while (x < b) { b = x; x = (a / x + x) / 2; } } else if (a != 0) { b = 1; } } function wmul(uint256 a, uint256 b) internal pure returns (uint256) { return mul(a, b) / WAD; } function wmulRound(uint256 a, uint256 b) internal pure returns (uint256) { return add(mul(a, b), WAD / 2) / WAD; } function rmul(uint256 a, uint256 b) internal pure returns (uint256) { return mul(a, b) / RAY; } function rmulRound(uint256 a, uint256 b) internal pure returns (uint256) { return add(mul(a, b), RAY / 2) / RAY; } function wdiv(uint256 a, uint256 b) internal pure returns (uint256) { return div(mul(a, WAD), b); } function wdivRound(uint256 a, uint256 b) internal pure returns (uint256) { return add(mul(a, WAD), b / 2) / b; } function rdiv(uint256 a, uint256 b) internal pure returns (uint256) { return div(mul(a, RAY), b); } function rdivRound(uint256 a, uint256 b) internal pure returns (uint256) { return add(mul(a, RAY), b / 2) / b; } function wpow(uint256 x, uint256 n) internal pure returns (uint256) { uint256 result = WAD; while (n > 0) { if (n % 2 != 0) { result = wmul(result, x); } x = wmul(x, x); n /= 2; } return result; } function rpow(uint256 x, uint256 n) internal pure returns (uint256) { uint256 result = RAY; while (n > 0) { if (n % 2 != 0) { result = rmul(result, x); } x = rmul(x, x); n /= 2; } return result; } function divCeil(uint256 a, uint256 b) internal pure returns (uint256) { uint256 quotient = div(a, b); uint256 remainder = a - quotient * b; if (remainder > 0) { return quotient + 1; } else { return quotient; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @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 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 sqrtPriceX96 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 sqrtPriceX96) { uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); require(absTick <= uint256(uint24(MAX_TICK)), "T"); uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; 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 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; if (tick > 0) ratio = type(uint256).max / 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 sqrtPriceX96 = uint160( (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1) ); } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtPriceX96 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 sqrtPriceX96) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require( sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, "R" ); uint256 ratio = uint256(sqrtPriceX96) << 32; uint256 r = ratio; uint256 msb = 0; 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) <= sqrtPriceX96 ? tickHi : tickLow; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SafeMath} from "./SafeMath.sol"; import {IERC20} from "../interfaces/IERC20.sol"; import {SafeERC20} from "./SafeERC20.sol"; library UniversalERC20 { using SafeMath for uint256; using SafeERC20 for IERC20; IERC20 private constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); function universalTransfer( IERC20 token, address payable to, uint256 amount ) internal { if (amount > 0) { if (isETH(token)) { to.transfer(amount); } else { token.safeTransfer(to, amount); } } } function universalTransferFrom( IERC20 token, address from, address payable to, uint256 amount ) internal { if (amount > 0) { token.safeTransferFrom(from, to, amount); } } function universalApproveMax( IERC20 token, address to, uint256 amount ) internal { uint256 allowance = token.allowance(address(this), to); if (allowance < amount) { token.forceApprove(to, type(uint256).max); } } function universalBalanceOf(IERC20 token, address who) internal view returns (uint256) { if (isETH(token)) { return who.balance; } else { return token.balanceOf(who); } } function tokenBalanceOf(IERC20 token, address who) internal view returns (uint256) { return token.balanceOf(who); } function isETH(IERC20 token) internal pure returns (bool) { return token == ETH_ADDRESS; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address payable","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"moreInfo","type":"bytes"}],"name":"sellBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"moreInfo","type":"bytes"}],"name":"sellQuote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b50604051610b98380380610b9883398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610af961009f60003960008181606b0152818161041f0152818161046501526104fa0152610af96000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806330e6ae31146100515780636f7929f214610051578063ad5c464814610066578063fa461e33146100a9575b600080fd5b61006461005f36600461072f565b6100bc565b005b61008d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100646100b73660046107d4565b6100f3565b600080828060200190518101906100d39190610878565b9092509050601f193601356100eb8686858585610190565b505050505050565b60008413806101025750600083135b61010b57600080fd5b60008061011a83850185610916565b50915091506000806000881361014557836001600160a01b0316836001600160a01b0316108761015c565b826001600160a01b0316846001600160a01b031610885b915091508115610177576101728430338461041d565b610186565b8293506101868430338461041d565b5050505050505050565b6000650f2882bf0b3360d21b808316036101a75750805b600080848060200190518101906101be9190610961565b506040516370a0823160e01b815230600482015291935091506000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f91906109a3565b90506000826001600160a01b0316846001600160a01b0316109050886001600160a01b031663128acb088b83858c6001600160a01b0316600014610273578c6102ac565b8561029c57610297600173fffd8963efd1fc6a506488495d951d5263988d266109d2565b6102ac565b6102ac6401000276a360016109f9565b8c6040518663ffffffff1660e01b81526004016102cd959493929190610a19565b60408051808303816000875af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190610a76565b50506040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015610358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037c91906109a3565b905060008111801561039657506001600160a01b03861615155b156104105760405163a9059cbb60e01b81526001600160a01b0387811660048301526024820183905286169063a9059cbb906044016020604051808303816000875af11580156103ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040e9190610a9a565b505b5050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561045e5750804710155b15610571577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156104be57600080fd5b505af11580156104d2573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018690527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190610a9a565b5061059d565b306001600160a01b038416036105915761058c8483836105a3565b61059d565b61059d848484846105d8565b50505050565b6105b68363a9059cbb60e01b8484610654565b6105d35760405163fb7f507960e01b815260040160405180910390fd5b505050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af19150508015610636573d801561062c57600160005114601f3d11169150610634565b6000873b1191505b505b806100eb5760405163f405907160e01b815260040160405180910390fd5b60006040518481528360048201528260248201526020600060448360008a5af191505080156106a0573d801561069657600160005114601f3d1116915061069e565b6000863b1191505b505b949350505050565b6001600160a01b03811681146106bd57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156106ff576106ff6106c0565b604052919050565b600067ffffffffffffffff821115610721576107216106c0565b50601f01601f191660200190565b60008060006060848603121561074457600080fd5b833561074f816106a8565b9250602084013561075f816106a8565b9150604084013567ffffffffffffffff81111561077b57600080fd5b8401601f8101861361078c57600080fd5b803561079f61079a82610707565b6106d6565b8181528760208385010111156107b457600080fd5b816020840160208301376000602083830101528093505050509250925092565b600080600080606085870312156107ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561081057600080fd5b818701915087601f83011261082457600080fd5b81358181111561083357600080fd5b88602082850101111561084557600080fd5b95989497505060200194505050565b60005b8381101561086f578181015183820152602001610857565b50506000910152565b6000806040838503121561088b57600080fd5b8251610896816106a8565b602084015190925067ffffffffffffffff8111156108b357600080fd5b8301601f810185136108c457600080fd5b80516108d261079a82610707565b8181528660208385010111156108e757600080fd5b6108f8826020830160208601610854565b8093505050509250929050565b62ffffff811681146106bd57600080fd5b60008060006060848603121561092b57600080fd5b8335610936816106a8565b92506020840135610946816106a8565b9150604084013561095681610905565b809150509250925092565b60008060006060848603121561097657600080fd5b8351610981816106a8565b6020850151909350610992816106a8565b604085015190925061095681610905565b6000602082840312156109b557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038281168282160390808211156109f2576109f26109bc565b5092915050565b6001600160a01b038181168382160190808211156109f2576109f26109bc565b600060018060a01b038088168352861515602084015285604084015280851660608401525060a0608083015282518060a0840152610a5e8160c0850160208701610854565b601f01601f19169190910160c0019695505050505050565b60008060408385031215610a8957600080fd5b505080516020909101519092909150565b600060208284031215610aac57600080fd5b81518015158114610abc57600080fd5b939250505056fea2646970667358221220935ab1b0c40637893b9d243838fa7ad6cbd077fb4dfc4218ec97013be065995564736f6c63430008110033000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806330e6ae31146100515780636f7929f214610051578063ad5c464814610066578063fa461e33146100a9575b600080fd5b61006461005f36600461072f565b6100bc565b005b61008d7f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3881565b6040516001600160a01b03909116815260200160405180910390f35b6100646100b73660046107d4565b6100f3565b600080828060200190518101906100d39190610878565b9092509050601f193601356100eb8686858585610190565b505050505050565b60008413806101025750600083135b61010b57600080fd5b60008061011a83850185610916565b50915091506000806000881361014557836001600160a01b0316836001600160a01b0316108761015c565b826001600160a01b0316846001600160a01b031610885b915091508115610177576101728430338461041d565b610186565b8293506101868430338461041d565b5050505050505050565b6000650f2882bf0b3360d21b808316036101a75750805b600080848060200190518101906101be9190610961565b506040516370a0823160e01b815230600482015291935091506000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561020b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022f91906109a3565b90506000826001600160a01b0316846001600160a01b0316109050886001600160a01b031663128acb088b83858c6001600160a01b0316600014610273578c6102ac565b8561029c57610297600173fffd8963efd1fc6a506488495d951d5263988d266109d2565b6102ac565b6102ac6401000276a360016109f9565b8c6040518663ffffffff1660e01b81526004016102cd959493929190610a19565b60408051808303816000875af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190610a76565b50506040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015610358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037c91906109a3565b905060008111801561039657506001600160a01b03861615155b156104105760405163a9059cbb60e01b81526001600160a01b0387811660048301526024820183905286169063a9059cbb906044016020604051808303816000875af11580156103ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040e9190610a9a565b505b5050505050505050505050565b7f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad386001600160a01b0316846001600160a01b031614801561045e5750804710155b15610571577f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad386001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156104be57600080fd5b505af11580156104d2573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018690527f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3816935063a9059cbb925060440190506020604051808303816000875af1158015610547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056b9190610a9a565b5061059d565b306001600160a01b038416036105915761058c8483836105a3565b61059d565b61059d848484846105d8565b50505050565b6105b68363a9059cbb60e01b8484610654565b6105d35760405163fb7f507960e01b815260040160405180910390fd5b505050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af19150508015610636573d801561062c57600160005114601f3d11169150610634565b6000873b1191505b505b806100eb5760405163f405907160e01b815260040160405180910390fd5b60006040518481528360048201528260248201526020600060448360008a5af191505080156106a0573d801561069657600160005114601f3d1116915061069e565b6000863b1191505b505b949350505050565b6001600160a01b03811681146106bd57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156106ff576106ff6106c0565b604052919050565b600067ffffffffffffffff821115610721576107216106c0565b50601f01601f191660200190565b60008060006060848603121561074457600080fd5b833561074f816106a8565b9250602084013561075f816106a8565b9150604084013567ffffffffffffffff81111561077b57600080fd5b8401601f8101861361078c57600080fd5b803561079f61079a82610707565b6106d6565b8181528760208385010111156107b457600080fd5b816020840160208301376000602083830101528093505050509250925092565b600080600080606085870312156107ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561081057600080fd5b818701915087601f83011261082457600080fd5b81358181111561083357600080fd5b88602082850101111561084557600080fd5b95989497505060200194505050565b60005b8381101561086f578181015183820152602001610857565b50506000910152565b6000806040838503121561088b57600080fd5b8251610896816106a8565b602084015190925067ffffffffffffffff8111156108b357600080fd5b8301601f810185136108c457600080fd5b80516108d261079a82610707565b8181528660208385010111156108e757600080fd5b6108f8826020830160208601610854565b8093505050509250929050565b62ffffff811681146106bd57600080fd5b60008060006060848603121561092b57600080fd5b8335610936816106a8565b92506020840135610946816106a8565b9150604084013561095681610905565b809150509250925092565b60008060006060848603121561097657600080fd5b8351610981816106a8565b6020850151909350610992816106a8565b604085015190925061095681610905565b6000602082840312156109b557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038281168282160390808211156109f2576109f26109bc565b5092915050565b6001600160a01b038181168382160190808211156109f2576109f26109bc565b600060018060a01b038088168352861515602084015285604084015280851660608401525060a0608083015282518060a0840152610a5e8160c0850160208701610854565b601f01601f19169190910160c0019695505050505050565b60008060408385031215610a8957600080fd5b505080516020909101519092909150565b600060208284031215610aac57600080fd5b81518015158114610abc57600080fd5b939250505056fea2646970667358221220935ab1b0c40637893b9d243838fa7ad6cbd077fb4dfc4218ec97013be065995564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38
-----Decoded View---------------
Arg [0] : weth (address): 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.