Source Code
Latest 25 from a total of 47 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Usdc | 22641324 | 25 hrs ago | IN | 0 ETH | 0.00084896 | ||||
Withdraw Weth | 22641317 | 25 hrs ago | IN | 0 ETH | 0.00084501 | ||||
Withdraw Weth | 22641310 | 25 hrs ago | IN | 0 ETH | 0.00090906 | ||||
Withdraw Weth | 22641272 | 25 hrs ago | IN | 0 ETH | 0.00098884 | ||||
Deposit Usdc | 22641265 | 25 hrs ago | IN | 0 ETH | 0.00081995 | ||||
Approve Usdc | 22641261 | 25 hrs ago | IN | 0 ETH | 0.00031205 | ||||
Withdraw Weth | 22641229 | 25 hrs ago | IN | 0 ETH | 0.00088052 | ||||
Deposit ETH | 22641212 | 25 hrs ago | IN | 0.002 ETH | 0.00072457 | ||||
Approve Weth | 22641091 | 25 hrs ago | IN | 0 ETH | 0.00037822 | ||||
Approve Weth | 22641039 | 26 hrs ago | IN | 0 ETH | 0.00054121 | ||||
Withdraw Usdc | 22633835 | 2 days ago | IN | 0 ETH | 0.00168495 | ||||
Deposit Usdc | 22633834 | 2 days ago | IN | 0 ETH | 0.00137571 | ||||
Deposit Usdc | 22633829 | 2 days ago | IN | 0 ETH | 0.00148092 | ||||
Approve Usdc | 22633818 | 2 days ago | IN | 0 ETH | 0.00064481 | ||||
Deposit Usdc | 22633712 | 2 days ago | IN | 0 ETH | 0.00183807 | ||||
Deposit Usdc | 22633711 | 2 days ago | IN | 0 ETH | 0.00201467 | ||||
Approve Usdc | 22633703 | 2 days ago | IN | 0 ETH | 0.00071476 | ||||
Withdraw Usdc | 22633685 | 2 days ago | IN | 0 ETH | 0.00117399 | ||||
Withdraw Weth | 22633659 | 2 days ago | IN | 0 ETH | 0.0011549 | ||||
Deposit ETH | 22633645 | 2 days ago | IN | 0.002 ETH | 0.00088069 | ||||
Withdraw Usdc | 22631454 | 2 days ago | IN | 0 ETH | 0.00130988 | ||||
Deposit Usdc | 22631448 | 2 days ago | IN | 0 ETH | 0.00100891 | ||||
Approve Usdc | 22631441 | 2 days ago | IN | 0 ETH | 0.00035909 | ||||
Withdraw Weth | 22631426 | 2 days ago | IN | 0 ETH | 0.00086271 | ||||
Withdraw Usdc | 22631383 | 2 days ago | IN | 0 ETH | 0.00096788 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
Transfer | 22641317 | 25 hrs ago | 0.001 ETH | ||||
Transfer | 22641317 | 25 hrs ago | 0.001 ETH | ||||
Transfer | 22641310 | 25 hrs ago | 0.001 ETH | ||||
Transfer | 22641310 | 25 hrs ago | 0.001 ETH | ||||
Transfer | 22641272 | 25 hrs ago | 0 ETH | ||||
Transfer | 22641272 | 25 hrs ago | 0 ETH | ||||
Transfer | 22641229 | 25 hrs ago | 0.002 ETH | ||||
Transfer | 22641229 | 25 hrs ago | 0.002 ETH | ||||
Deposit | 22641212 | 25 hrs ago | 0.002 ETH | ||||
Transfer | 22633659 | 2 days ago | 0.003 ETH | ||||
Transfer | 22633659 | 2 days ago | 0.003 ETH | ||||
Deposit | 22633645 | 2 days ago | 0.002 ETH | ||||
Transfer | 22631426 | 2 days ago | 0.001 ETH | ||||
Transfer | 22631426 | 2 days ago | 0.001 ETH | ||||
Transfer | 22631221 | 2 days ago | 0.01 ETH | ||||
Transfer | 22631221 | 2 days ago | 0.01 ETH | ||||
Deposit | 22629771 | 2 days ago | 0.001 ETH | ||||
Deposit | 22629518 | 2 days ago | 0.01 ETH | ||||
Deposit | 22629130 | 2 days ago | 0.01 ETH | ||||
Deposit | 22628914 | 2 days ago | 0.001 ETH | ||||
Transfer | 22624930 | 3 days ago | 0.001 ETH | ||||
Transfer | 22624930 | 3 days ago | 0.001 ETH | ||||
Deposit | 22624911 | 3 days ago | 0.001 ETH | ||||
Transfer | 22616393 | 4 days ago | 0.001 ETH | ||||
Transfer | 22616393 | 4 days ago | 0.001 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PositionUSDCETH
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "./lib/UniswapUtil.sol"; interface IWETH { function deposit() external payable; function withdraw(uint256) external; } interface IUniswapV3PositionManager { function increaseLiquidity( IncreaseLiquidityParams calldata params ) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1); struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; } function decreaseLiquidity( DecreaseLiquidityParams calldata params ) external payable returns (uint256 amount0, uint256 amount1); function collect( CollectParams calldata params ) external payable returns (uint256 amount0, uint256 amount1); function positions( uint256 tokenId ) external view returns ( uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); function safeTransferFrom( address from, address to, uint256 tokenId ) external; function ownerOf(uint256 tokenId) external view returns (address); } //USDC资金池: https://app.uniswap.org/positions/v3/ethereum/998458 //ETH资金池: https://app.uniswap.org/positions/v3/ethereum/998463 //存USDC前需要先授权给合约: //https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48#writeProxyContract //操作员: //https://etherscan.io/address/0x7fbE4E83f219E9EF26B222E74850bD3A081814E1#writeContract contract PositionUSDCETH is AccessControl, IERC721Receiver { using SafeERC20 for IERC20; IUniswapV3PositionManager public constant PositionManager = IUniswapV3PositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; uint256 public wethTokenId; uint256 public usdcTokenId; constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); IERC20(WETH).approve(address(PositionManager), type(uint256).max); IERC20(USDC).approve(address(PositionManager), type(uint256).max); } function setTokenId( uint256 _wethTokenId, uint256 _usdcTokenId ) external onlyRole(DEFAULT_ADMIN_ROLE) { wethTokenId = _wethTokenId; usdcTokenId = _usdcTokenId; } function depositETH() external payable { require(wethTokenId != 0, "TokenId not set"); // 将ETH转换为WETH IWETH(WETH).deposit{value: msg.value}(); increaseLiquidity(msg.value, wethTokenId); } function depositUsdc(uint256 usdcAmount) external { require(usdcTokenId != 0, "TokenId not set"); IERC20(USDC).transferFrom(msg.sender, address(this), usdcAmount); increaseLiquidity(usdcAmount, usdcTokenId); } function increaseLiquidity(uint256 amount, uint256 tokenId) internal { if (tokenId == usdcTokenId) { PositionManager.increaseLiquidity( IUniswapV3PositionManager.IncreaseLiquidityParams({ tokenId: tokenId, amount0Desired: amount, amount1Desired: 0, amount0Min: (amount * 99) / 100, amount1Min: 0, deadline: block.timestamp }) ); } else { PositionManager.increaseLiquidity( IUniswapV3PositionManager.IncreaseLiquidityParams({ tokenId: tokenId, amount0Desired: 0, amount1Desired: amount, amount0Min: 0, amount1Min: (amount * 99) / 100, deadline: block.timestamp }) ); } } /** * @dev 估算指定金额对应的流动性数量 * @param tokenId NFT的ID * @param amount 要移除的代币数量 * @return liquidity 估算的流动性数量 */ function estimateLiquidityAmount( uint256 tokenId, uint256 amount ) public view returns (uint128 liquidity) { (, , , , , int24 tickLower, int24 tickUpper, , , , , ) = PositionManager .positions(tokenId); uint160 sqrtRatioAX96 = UniswapUtil.getSqrtRatioAtTick(tickLower); uint160 sqrtRatioBX96 = UniswapUtil.getSqrtRatioAtTick(tickUpper); if (tokenId == usdcTokenId) { // 对于USDC池子,使用amount0 liquidity = UniswapUtil.getLiquidityForAmount0( sqrtRatioAX96, sqrtRatioBX96, (amount * 1000001) / 1000000 ); } else { // 对于WETH池子,使用amount1 liquidity = UniswapUtil.getLiquidityForAmount1( sqrtRatioAX96, sqrtRatioBX96, (amount * 1000001) / 1000000 ); } } function withdrawWeth( uint256 amount, address recipient ) external onlyRole(DEFAULT_ADMIN_ROLE) { decreaseLiquidityAndCollect(wethTokenId, amount, recipient); } function withdrawUsdc( uint256 amount, address recipient ) external onlyRole(DEFAULT_ADMIN_ROLE) { decreaseLiquidityAndCollect(usdcTokenId, amount, recipient); } /** * @dev 移除流动性并收集代币到指定地址 * @param tokenId NFT的ID * @param amount 要移除的代币数量 * @param recipient 接收代币的地址 */ function decreaseLiquidityAndCollect( uint256 tokenId, uint256 amount, address recipient ) private { require( tokenId == wethTokenId || tokenId == usdcTokenId, "Invalid tokenId" ); require(recipient != address(0), "Invalid recipient"); // 估算需要移除的流动性数量 uint128 liquidityToRemove = estimateLiquidityAmount(tokenId, amount); require(liquidityToRemove > 0, "Liquidity too small"); _decreaseLiquidityAndCollect(tokenId, liquidityToRemove, recipient); } /** * @dev 内部函数:移除指定数量的流动性并收集代币到指定地址 * @param tokenId NFT的ID * @param liquidityToRemove 要移除的流动性数量 * @param recipient 接收代币的地址 * @return amount0 收集的token0数量 * @return amount1 收集的token1数量 */ function _decreaseLiquidityAndCollect( uint256 tokenId, uint128 liquidityToRemove, address recipient ) internal returns (uint256 amount0, uint256 amount1) { // 减少流动性 (uint256 collected0, uint256 collected1) = PositionManager .decreaseLiquidity( IUniswapV3PositionManager.DecreaseLiquidityParams({ tokenId: tokenId, liquidity: liquidityToRemove, amount0Min: 0, // 可以设置滑点保护 amount1Min: 0, // 可以设置滑点保护 deadline: block.timestamp }) ); // 收集代币并发送到指定地址 (amount0, amount1) = PositionManager.collect( IUniswapV3PositionManager.CollectParams({ tokenId: tokenId, recipient: address(this), // 先收集到合约 amount0Max: uint128(collected0), amount1Max: uint128(collected1) }) ); // 将代币转给接收者 if (amount0 > 0) { IERC20(USDC).safeTransfer(recipient, amount0); } if (amount1 > 0) { // 如果是ETH池子,需要将WETH转换为ETH if (tokenId == wethTokenId) { IWETH(WETH).withdraw(amount1); (bool success, ) = recipient.call{value: amount1}(""); require(success, "ETH transfer failed"); } else { IERC20(WETH).safeTransfer(recipient, amount1); } } } /** * @dev 收集已累积的手续费而不减少流动性 * @param tokenId NFT的ID * @param recipient 接收手续费的地址 * @return amount0 收集的token0数量 * @return amount1 收集的token1数量 */ function collectFees( uint256 tokenId, address recipient ) private returns (uint256 amount0, uint256 amount1) { require( tokenId == wethTokenId || tokenId == usdcTokenId, "Invalid tokenId" ); require(recipient != address(0), "Invalid recipient"); // 收集所有累积的手续费 (amount0, amount1) = PositionManager.collect( IUniswapV3PositionManager.CollectParams({ tokenId: tokenId, recipient: address(this), // 先收集到合约 amount0Max: type(uint128).max, amount1Max: type(uint128).max }) ); // 将代币转给接收者 if (amount0 > 0) { IERC20(USDC).safeTransfer(recipient, amount0); } if (amount1 > 0) { // 如果是ETH池子,需要将WETH转换为ETH if (tokenId == wethTokenId) { IWETH(WETH).withdraw(amount1); (bool success, ) = recipient.call{value: amount1}(""); require(success, "ETH transfer failed"); } else { IERC20(WETH).safeTransfer(recipient, amount1); } } } /** * @dev 将NFT从合约转移到指定地址 * @param tokenId NFT的ID * @param recipient 接收NFT的地址 */ function transferNFT( uint256 tokenId, address recipient ) external onlyRole(DEFAULT_ADMIN_ROLE) { require( tokenId == wethTokenId || tokenId == usdcTokenId, "Invalid tokenId" ); require(recipient != address(0), "Invalid recipient"); // 如果是WETH的NFT,更新状态变量 if (tokenId == wethTokenId) { wethTokenId = 0; } // 如果是USDC的NFT,更新状态变量 if (tokenId == usdcTokenId) { usdcTokenId = 0; } // 转移NFT // 使用safeTransferFrom确保接收者能够处理ERC721代币 PositionManager.safeTransferFrom(address(this), recipient, tokenId); } function approveWeth(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) { IERC20(WETH).approve(address(PositionManager), amount); } function approveUsdc(uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) { IERC20(USDC).approve(address(PositionManager), amount); } /** * @dev 实现IERC721Receiver接口,允许合约接收ERC721代币(NFT) */ function onERC721Received( address, // operator address, // from uint256, // tokenId bytes calldata // data ) external pure override returns (bytes4) { // 不进行状态修改,只返回选择器 return this.onERC721Received.selector; } /** * @dev 设置从外部接收的NFT * @param _tokenId NFT的ID * @param isWeth 是否为WETH的NFT */ function setReceivedNFT( uint256 _tokenId, bool isWeth ) external onlyRole(DEFAULT_ADMIN_ROLE) { // 验证NFT确实由合约持有 require( PositionManager.ownerOf(_tokenId) == address(this), "Contract does not own this NFT" ); if (isWeth) { wethTokenId = _tokenId; } else { usdcTokenId = _tokenId; } } receive() external payable {} }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; library UniswapUtil { error T(); int24 internal constant MIN_TICK = -887272; int24 internal constant MAX_TICK = -MIN_TICK; uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { unchecked { uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); if (absTick > uint256(int256(MAX_TICK))) revert 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; sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } } function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { uint256 prod0; uint256 prod1; assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } require(denominator > prod1); uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } uint256 twos = (0 - denominator) & denominator; assembly { denominator := div(denominator, twos) } assembly { prod0 := div(prod0, twos) } assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; uint256 inv = (3 * denominator) ^ 2; inv *= 2 - denominator * inv; inv *= 2 - denominator * inv; inv *= 2 - denominator * inv; inv *= 2 - denominator * inv; inv *= 2 - denominator * inv; inv *= 2 - denominator * inv; result = prod0 * inv; return result; } } function toUint128(uint256 x) private pure returns (uint128 y) { require((y = uint128(x)) == x); } function getLiquidityForAmount0(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); uint256 intermediate = mulDiv(sqrtRatioAX96, sqrtRatioBX96, Q96); unchecked { return toUint128(mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96)); } } function getLiquidityForAmount1(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); unchecked { return toUint128(mulDiv(amount1, Q96, sqrtRatioBX96 - sqrtRatioAX96)); } } 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); } } function getAmount0ForLiquidity(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity) internal pure returns (uint256 amount0) { unchecked { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return mulDiv(uint256(liquidity) << RESOLUTION, sqrtRatioBX96 - sqrtRatioAX96, sqrtRatioBX96) / sqrtRatioAX96; } } function getAmount1ForLiquidity(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity) internal pure returns (uint256 amount1) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); unchecked { return mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, Q96); } } 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 v5.1.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 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: MIT // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted to signal this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "remappings": [], "evmVersion": "shanghai" }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"T","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PositionManager","outputs":[{"internalType":"contract IUniswapV3PositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveWeth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdcAmount","type":"uint256"}],"name":"depositUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"estimateLiquidityAmount","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"isWeth","type":"bool"}],"name":"setReceivedNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wethTokenId","type":"uint256"},{"internalType":"uint256","name":"_usdcTokenId","type":"uint256"}],"name":"setTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"transferNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdcTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawWeth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561000f575f80fd5b5061001a5f3361013c565b5060405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201525f19602482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063095ea7b3906044016020604051808303815f875af1158015610084573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a891906101e5565b5060405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201525f19602482015273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063095ea7b3906044016020604051808303815f875af1158015610112573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013691906101e5565b5061020b565b5f828152602081815260408083206001600160a01b038516845290915281205460ff166101dc575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101943390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016101df565b505f5b92915050565b5f602082840312156101f5575f80fd5b81518015158114610204575f80fd5b9392505050565b611b04806102185f395ff3fe60806040526004361061013f575f3560e01c806389a30271116100b3578063d547741f1161006d578063d547741f146103da578063db743165146103f9578063df1e664614610418578063ebe0789814610437578063f6326fb314610456578063fdba27d61461045e575f80fd5b806389a30271146102fc5780639036c0501461033b57806391d148541461035a578063a217fddf14610379578063ad5c46481461038c578063ca1e1db4146103b3575f80fd5b80632357928e116101045780632357928e1461021b578063248a9ca31461023a5780632f2ff15d1461026857806336568abe1461028757806367b479fa146102a65780637b656209146102dd575f80fd5b806301ffc9a71461014a57806302a0ba3f1461017e57806311bd3c3d1461019f578063150b7a02146101c25780631c83ab2f14610206575f80fd5b3661014657005b5f80fd5b348015610155575f80fd5b50610169610164366004611724565b61047d565b60405190151581526020015b60405180910390f35b348015610189575f80fd5b5061019d61019836600461175f565b6104b3565b005b3480156101aa575f80fd5b506101b460025481565b604051908152602001610175565b3480156101cd575f80fd5b506101ed6101dc36600461178d565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610175565b348015610211575f80fd5b506101b460015481565b348015610226575f80fd5b5061019d610235366004611826565b6104cf565b348015610245575f80fd5b506101b4610254366004611826565b5f9081526020819052604090206001015490565b348015610273575f80fd5b5061019d61028236600461175f565b6105a6565b348015610292575f80fd5b5061019d6102a136600461175f565b6105d0565b3480156102b1575f80fd5b506102c56102c036600461183d565b610603565b6040516001600160801b039091168152602001610175565b3480156102e8575f80fd5b5061019d6102f736600461175f565b610709565b348015610307575f80fd5b5061032373a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6040516001600160a01b039091168152602001610175565b348015610346575f80fd5b5061019d61035536600461175f565b610720565b348015610365575f80fd5b5061016961037436600461175f565b610859565b348015610384575f80fd5b506101b45f81565b348015610397575f80fd5b5061032373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b3480156103be575f80fd5b5061032373c36442b4a4522e871399cd717abdd847ab11fe8881565b3480156103e5575f80fd5b5061019d6103f436600461175f565b610881565b348015610404575f80fd5b5061019d61041336600461186a565b6108a5565b348015610423575f80fd5b5061019d610432366004611826565b61098d565b348015610442575f80fd5b5061019d610451366004611826565b610a25565b61019d610a81565b348015610469575f80fd5b5061019d61047836600461183d565b610b36565b5f6001600160e01b03198216637965db0b60e01b14806104ad57506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6104bd81610b4c565b6104ca6001548484610b56565b505050565b6002545f036105175760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b9259081b9bdd081cd95d608a1b60448201526064015b60405180910390fd5b6040516323b872dd60e01b81523360048201523060248201526044810182905273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906323b872dd906064016020604051808303815f875af1158015610572573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610596919061188d565b506105a381600254610c5d565b50565b5f828152602081905260409020600101546105c081610b4c565b6105ca8383610db9565b50505050565b6001600160a01b03811633146105f95760405163334bd91960e11b815260040160405180910390fd5b6104ca8282610e48565b60405163133f757160e31b8152600481018390525f908190819073c36442b4a4522e871399cd717abdd847ab11fe88906399fbab889060240161018060405180830381865afa158015610658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061067c91906118ec565b50505050509650965050505050505f61069483610eb1565b90505f6106a083610eb1565b905060025487036106d7576106d08282620f42406106c18a620f42416119c6565b6106cb91906119fd565b6111cc565b94506106ff565b6106fc8282620f42406106ed8a620f42416119c6565b6106f791906119fd565b611238565b94505b5050505092915050565b5f61071381610b4c565b6104ca6002548484610b56565b5f61072a81610b4c565b60015483148061073b575060025483145b6107795760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b604482015260640161050e565b6001600160a01b0382166107c35760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161050e565b60015483036107d1575f6001555b60025483036107df575f6002555b604051632142170760e11b81523060048201526001600160a01b03831660248201526044810184905273c36442b4a4522e871399cd717abdd847ab11fe88906342842e0e906064015f604051808303815f87803b15801561083e575f80fd5b505af1158015610850573d5f803e3d5ffd5b50505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8281526020819052604090206001015461089b81610b4c565b6105ca8383610e48565b5f6108af81610b4c565b6040516331a9108f60e11b815260048101849052309073c36442b4a4522e871399cd717abdd847ab11fe8890636352211e90602401602060405180830381865afa1580156108ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109239190611a1c565b6001600160a01b0316146109795760405162461bcd60e51b815260206004820152601e60248201527f436f6e747261637420646f6573206e6f74206f776e2074686973204e46540000604482015260640161050e565b8115610986575050600155565b5050600255565b5f61099781610b4c565b60405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201526024810183905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063095ea7b3906044015b6020604051808303815f875af1158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ca919061188d565b5f610a2f81610b4c565b60405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201526024810183905273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063095ea7b3906044016109e5565b6001545f03610ac45760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b9259081b9bdd081cd95d608a1b604482015260640161050e565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610b11575f80fd5b505af1158015610b23573d5f803e3d5ffd5b5050505050610b3434600154610c5d565b565b5f610b4081610b4c565b50600191909155600255565b6105a3813361127c565b600154831480610b67575060025483145b610ba55760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b604482015260640161050e565b6001600160a01b038116610bef5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161050e565b5f610bfa8484610603565b90505f816001600160801b031611610c4a5760405162461bcd60e51b8152602060048201526013602482015272131a5c5d5a591a5d1e481d1bdbc81cdb585b1b606a1b604482015260640161050e565b610c558482846112b5565b505050505050565b6002548103610d315773c36442b4a4522e871399cd717abdd847ab11fe886001600160a01b031663219f5d176040518060c001604052808481526020018581526020015f81526020016064866063610cb591906119c6565b610cbf91906119fd565b81526020015f8152602001428152506040518263ffffffff1660e01b8152600401610cea9190611a37565b6060604051808303815f875af1158015610d06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d2a9190611a7a565b5050505050565b73c36442b4a4522e871399cd717abdd847ab11fe886001600160a01b031663219f5d176040518060c001604052808481526020015f81526020018581526020015f81526020016064866063610d8691906119c6565b610d9091906119fd565b8152602001428152506040518263ffffffff1660e01b8152600401610cea9190611a37565b5050565b5f610dc48383610859565b610e41575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610df93390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016104ad565b505f6104ad565b5f610e538383610859565b15610e41575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016104ad565b5f805f8360020b12610ec6578260020b610ecd565b8260020b5f035b9050620d89e8811115610ef3576040516315e4079d60e11b815260040160405180910390fd5b5f816001165f03610f0857600160801b610f1a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610f4e576ffff97272373d413259a46990580e213a0260801c5b6004821615610f6d576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610f8c576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610fab576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610fca576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610fe9576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611008576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611028576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611048576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611068576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611088576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156110a8576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156110c8576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156110e8576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611108576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611129576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611149576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611168576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611185576b048a170391f7dc42444e8fa20260801c5b5f8460020b13156111a457805f19816111a0576111a06119e9565b0490505b6401000000008106156111b85760016111ba565b5f5b60ff16602082901c0192505050919050565b5f826001600160a01b0316846001600160a01b031611156111eb579192915b5f61120d856001600160a01b0316856001600160a01b0316600160601b6115a5565b905061122d61122884838888036001600160a01b03166115a5565b61164f565b9150505b9392505050565b5f826001600160a01b0316846001600160a01b03161115611257579192915b61127461122883600160601b8787036001600160a01b03166115a5565b949350505050565b6112868282610859565b610db55760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161050e565b6040805160a0810182528481526001600160801b03848116602083019081525f8385018181526060850182815242608087019081529651630624e65f60e11b81529551600487015292519093166024850152915160448401525160648301529151608482015281908190819073c36442b4a4522e871399cd717abdd847ab11fe8890630c49ccbe9060a40160408051808303815f875af115801561135b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137f9190611aac565b604080516080810182528a815230602082019081526001600160801b0385811683850190815285821660608501908152945163fc6f786560e01b81529351600485015291516001600160a01b0316602484015290518116604483015291519091166064820152919350915073c36442b4a4522e871399cd717abdd847ab11fe889063fc6f78659060840160408051808303815f875af1158015611424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114489190611aac565b909450925083156114725761147273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488686611669565b821561159b57600154870361157c57604051632e1a7d4d60e01b81526004810184905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d906024015f604051808303815f87803b1580156114cb575f80fd5b505af11580156114dd573d5f803e3d5ffd5b505050505f856001600160a01b0316846040515f6040518083038185875af1925050503d805f811461152a576040519150601f19603f3d011682016040523d82523d5f602084013e61152f565b606091505b50509050806115765760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161050e565b5061159b565b61159b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28685611669565b5050935093915050565b5f80805f19858709858702925082811083820303915050805f036115d9575f84116115ce575f80fd5b508290049050611231565b8084116115e4575f80fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611664575f80fd5b919050565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180516001600160e01b031663a9059cbb60e01b17815282516104ca93879390925f9283929183919082885af1806116d7576040513d5f823e3d81fd5b50505f513d915081156116ee5780600114156116fb565b6001600160a01b0384163b155b156105ca57604051635274afe760e01b81526001600160a01b038516600482015260240161050e565b5f60208284031215611734575f80fd5b81356001600160e01b031981168114611231575f80fd5b6001600160a01b03811681146105a3575f80fd5b5f8060408385031215611770575f80fd5b8235915060208301356117828161174b565b809150509250929050565b5f805f805f608086880312156117a1575f80fd5b85356117ac8161174b565b945060208601356117bc8161174b565b935060408601359250606086013567ffffffffffffffff8111156117de575f80fd5b8601601f810188136117ee575f80fd5b803567ffffffffffffffff811115611804575f80fd5b886020828401011115611815575f80fd5b959894975092955050506020019190565b5f60208284031215611836575f80fd5b5035919050565b5f806040838503121561184e575f80fd5b50508035926020909101359150565b80151581146105a3575f80fd5b5f806040838503121561187b575f80fd5b8235915060208301356117828161185d565b5f6020828403121561189d575f80fd5b81516112318161185d565b80516116648161174b565b805162ffffff81168114611664575f80fd5b8051600281900b8114611664575f80fd5b80516001600160801b0381168114611664575f80fd5b5f805f805f805f805f805f806101808d8f031215611908575f80fd5b8c516bffffffffffffffffffffffff81168114611923575f80fd5b9b5061193160208e016118a8565b9a5061193f60408e016118a8565b995061194d60608e016118a8565b985061195b60808e016118b3565b975061196960a08e016118c5565b965061197760c08e016118c5565b955061198560e08e016118d6565b6101008e01516101208f0151919650945092506119a56101408e016118d6565b91506119b46101608e016118d6565b90509295989b509295989b509295989b565b80820281158282048414176104ad57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f82611a1757634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215611a2c575f80fd5b81516112318161174b565b5f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b5f805f60608486031215611a8c575f80fd5b611a95846118d6565b602085015160409095015190969495509392505050565b5f8060408385031215611abd575f80fd5b50508051602090910151909290915056fea264697066735822122047cd4696f6ef42a03166e498665875e315c33a49a7f9af8642be752f9314cf7764736f6c634300081a0033
Deployed Bytecode
0x60806040526004361061013f575f3560e01c806389a30271116100b3578063d547741f1161006d578063d547741f146103da578063db743165146103f9578063df1e664614610418578063ebe0789814610437578063f6326fb314610456578063fdba27d61461045e575f80fd5b806389a30271146102fc5780639036c0501461033b57806391d148541461035a578063a217fddf14610379578063ad5c46481461038c578063ca1e1db4146103b3575f80fd5b80632357928e116101045780632357928e1461021b578063248a9ca31461023a5780632f2ff15d1461026857806336568abe1461028757806367b479fa146102a65780637b656209146102dd575f80fd5b806301ffc9a71461014a57806302a0ba3f1461017e57806311bd3c3d1461019f578063150b7a02146101c25780631c83ab2f14610206575f80fd5b3661014657005b5f80fd5b348015610155575f80fd5b50610169610164366004611724565b61047d565b60405190151581526020015b60405180910390f35b348015610189575f80fd5b5061019d61019836600461175f565b6104b3565b005b3480156101aa575f80fd5b506101b460025481565b604051908152602001610175565b3480156101cd575f80fd5b506101ed6101dc36600461178d565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610175565b348015610211575f80fd5b506101b460015481565b348015610226575f80fd5b5061019d610235366004611826565b6104cf565b348015610245575f80fd5b506101b4610254366004611826565b5f9081526020819052604090206001015490565b348015610273575f80fd5b5061019d61028236600461175f565b6105a6565b348015610292575f80fd5b5061019d6102a136600461175f565b6105d0565b3480156102b1575f80fd5b506102c56102c036600461183d565b610603565b6040516001600160801b039091168152602001610175565b3480156102e8575f80fd5b5061019d6102f736600461175f565b610709565b348015610307575f80fd5b5061032373a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6040516001600160a01b039091168152602001610175565b348015610346575f80fd5b5061019d61035536600461175f565b610720565b348015610365575f80fd5b5061016961037436600461175f565b610859565b348015610384575f80fd5b506101b45f81565b348015610397575f80fd5b5061032373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b3480156103be575f80fd5b5061032373c36442b4a4522e871399cd717abdd847ab11fe8881565b3480156103e5575f80fd5b5061019d6103f436600461175f565b610881565b348015610404575f80fd5b5061019d61041336600461186a565b6108a5565b348015610423575f80fd5b5061019d610432366004611826565b61098d565b348015610442575f80fd5b5061019d610451366004611826565b610a25565b61019d610a81565b348015610469575f80fd5b5061019d61047836600461183d565b610b36565b5f6001600160e01b03198216637965db0b60e01b14806104ad57506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6104bd81610b4c565b6104ca6001548484610b56565b505050565b6002545f036105175760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b9259081b9bdd081cd95d608a1b60448201526064015b60405180910390fd5b6040516323b872dd60e01b81523360048201523060248201526044810182905273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906323b872dd906064016020604051808303815f875af1158015610572573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610596919061188d565b506105a381600254610c5d565b50565b5f828152602081905260409020600101546105c081610b4c565b6105ca8383610db9565b50505050565b6001600160a01b03811633146105f95760405163334bd91960e11b815260040160405180910390fd5b6104ca8282610e48565b60405163133f757160e31b8152600481018390525f908190819073c36442b4a4522e871399cd717abdd847ab11fe88906399fbab889060240161018060405180830381865afa158015610658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061067c91906118ec565b50505050509650965050505050505f61069483610eb1565b90505f6106a083610eb1565b905060025487036106d7576106d08282620f42406106c18a620f42416119c6565b6106cb91906119fd565b6111cc565b94506106ff565b6106fc8282620f42406106ed8a620f42416119c6565b6106f791906119fd565b611238565b94505b5050505092915050565b5f61071381610b4c565b6104ca6002548484610b56565b5f61072a81610b4c565b60015483148061073b575060025483145b6107795760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b604482015260640161050e565b6001600160a01b0382166107c35760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161050e565b60015483036107d1575f6001555b60025483036107df575f6002555b604051632142170760e11b81523060048201526001600160a01b03831660248201526044810184905273c36442b4a4522e871399cd717abdd847ab11fe88906342842e0e906064015f604051808303815f87803b15801561083e575f80fd5b505af1158015610850573d5f803e3d5ffd5b50505050505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8281526020819052604090206001015461089b81610b4c565b6105ca8383610e48565b5f6108af81610b4c565b6040516331a9108f60e11b815260048101849052309073c36442b4a4522e871399cd717abdd847ab11fe8890636352211e90602401602060405180830381865afa1580156108ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109239190611a1c565b6001600160a01b0316146109795760405162461bcd60e51b815260206004820152601e60248201527f436f6e747261637420646f6573206e6f74206f776e2074686973204e46540000604482015260640161050e565b8115610986575050600155565b5050600255565b5f61099781610b4c565b60405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201526024810183905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063095ea7b3906044015b6020604051808303815f875af1158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ca919061188d565b5f610a2f81610b4c565b60405163095ea7b360e01b815273c36442b4a4522e871399cd717abdd847ab11fe8860048201526024810183905273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063095ea7b3906044016109e5565b6001545f03610ac45760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b9259081b9bdd081cd95d608a1b604482015260640161050e565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015610b11575f80fd5b505af1158015610b23573d5f803e3d5ffd5b5050505050610b3434600154610c5d565b565b5f610b4081610b4c565b50600191909155600255565b6105a3813361127c565b600154831480610b67575060025483145b610ba55760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b604482015260640161050e565b6001600160a01b038116610bef5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161050e565b5f610bfa8484610603565b90505f816001600160801b031611610c4a5760405162461bcd60e51b8152602060048201526013602482015272131a5c5d5a591a5d1e481d1bdbc81cdb585b1b606a1b604482015260640161050e565b610c558482846112b5565b505050505050565b6002548103610d315773c36442b4a4522e871399cd717abdd847ab11fe886001600160a01b031663219f5d176040518060c001604052808481526020018581526020015f81526020016064866063610cb591906119c6565b610cbf91906119fd565b81526020015f8152602001428152506040518263ffffffff1660e01b8152600401610cea9190611a37565b6060604051808303815f875af1158015610d06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d2a9190611a7a565b5050505050565b73c36442b4a4522e871399cd717abdd847ab11fe886001600160a01b031663219f5d176040518060c001604052808481526020015f81526020018581526020015f81526020016064866063610d8691906119c6565b610d9091906119fd565b8152602001428152506040518263ffffffff1660e01b8152600401610cea9190611a37565b5050565b5f610dc48383610859565b610e41575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055610df93390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016104ad565b505f6104ad565b5f610e538383610859565b15610e41575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016104ad565b5f805f8360020b12610ec6578260020b610ecd565b8260020b5f035b9050620d89e8811115610ef3576040516315e4079d60e11b815260040160405180910390fd5b5f816001165f03610f0857600160801b610f1a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610f4e576ffff97272373d413259a46990580e213a0260801c5b6004821615610f6d576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610f8c576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610fab576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610fca576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610fe9576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611008576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611028576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611048576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611068576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611088576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156110a8576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156110c8576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156110e8576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611108576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611129576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611149576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611168576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611185576b048a170391f7dc42444e8fa20260801c5b5f8460020b13156111a457805f19816111a0576111a06119e9565b0490505b6401000000008106156111b85760016111ba565b5f5b60ff16602082901c0192505050919050565b5f826001600160a01b0316846001600160a01b031611156111eb579192915b5f61120d856001600160a01b0316856001600160a01b0316600160601b6115a5565b905061122d61122884838888036001600160a01b03166115a5565b61164f565b9150505b9392505050565b5f826001600160a01b0316846001600160a01b03161115611257579192915b61127461122883600160601b8787036001600160a01b03166115a5565b949350505050565b6112868282610859565b610db55760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161050e565b6040805160a0810182528481526001600160801b03848116602083019081525f8385018181526060850182815242608087019081529651630624e65f60e11b81529551600487015292519093166024850152915160448401525160648301529151608482015281908190819073c36442b4a4522e871399cd717abdd847ab11fe8890630c49ccbe9060a40160408051808303815f875af115801561135b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137f9190611aac565b604080516080810182528a815230602082019081526001600160801b0385811683850190815285821660608501908152945163fc6f786560e01b81529351600485015291516001600160a01b0316602484015290518116604483015291519091166064820152919350915073c36442b4a4522e871399cd717abdd847ab11fe889063fc6f78659060840160408051808303815f875af1158015611424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114489190611aac565b909450925083156114725761147273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488686611669565b821561159b57600154870361157c57604051632e1a7d4d60e01b81526004810184905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d906024015f604051808303815f87803b1580156114cb575f80fd5b505af11580156114dd573d5f803e3d5ffd5b505050505f856001600160a01b0316846040515f6040518083038185875af1925050503d805f811461152a576040519150601f19603f3d011682016040523d82523d5f602084013e61152f565b606091505b50509050806115765760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161050e565b5061159b565b61159b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28685611669565b5050935093915050565b5f80805f19858709858702925082811083820303915050805f036115d9575f84116115ce575f80fd5b508290049050611231565b8084116115e4575f80fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611664575f80fd5b919050565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180516001600160e01b031663a9059cbb60e01b17815282516104ca93879390925f9283929183919082885af1806116d7576040513d5f823e3d81fd5b50505f513d915081156116ee5780600114156116fb565b6001600160a01b0384163b155b156105ca57604051635274afe760e01b81526001600160a01b038516600482015260240161050e565b5f60208284031215611734575f80fd5b81356001600160e01b031981168114611231575f80fd5b6001600160a01b03811681146105a3575f80fd5b5f8060408385031215611770575f80fd5b8235915060208301356117828161174b565b809150509250929050565b5f805f805f608086880312156117a1575f80fd5b85356117ac8161174b565b945060208601356117bc8161174b565b935060408601359250606086013567ffffffffffffffff8111156117de575f80fd5b8601601f810188136117ee575f80fd5b803567ffffffffffffffff811115611804575f80fd5b886020828401011115611815575f80fd5b959894975092955050506020019190565b5f60208284031215611836575f80fd5b5035919050565b5f806040838503121561184e575f80fd5b50508035926020909101359150565b80151581146105a3575f80fd5b5f806040838503121561187b575f80fd5b8235915060208301356117828161185d565b5f6020828403121561189d575f80fd5b81516112318161185d565b80516116648161174b565b805162ffffff81168114611664575f80fd5b8051600281900b8114611664575f80fd5b80516001600160801b0381168114611664575f80fd5b5f805f805f805f805f805f806101808d8f031215611908575f80fd5b8c516bffffffffffffffffffffffff81168114611923575f80fd5b9b5061193160208e016118a8565b9a5061193f60408e016118a8565b995061194d60608e016118a8565b985061195b60808e016118b3565b975061196960a08e016118c5565b965061197760c08e016118c5565b955061198560e08e016118d6565b6101008e01516101208f0151919650945092506119a56101408e016118d6565b91506119b46101608e016118d6565b90509295989b509295989b509295989b565b80820281158282048414176104ad57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f82611a1757634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215611a2c575f80fd5b81516112318161174b565b5f60c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b5f805f60608486031215611a8c575f80fd5b611a95846118d6565b602085015160409095015190969495509392505050565b5f8060408385031215611abd575f80fd5b50508051602090910151909290915056fea264697066735822122047cd4696f6ef42a03166e498665875e315c33a49a7f9af8642be752f9314cf7764736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,478.02 | 0.008 | $19.82 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.