// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {IMikoLaunchClock} from "./WeeklyRewardController.sol";
interface IControllerOwner {
function owner() external view returns (address);
}
interface IAllowanceTransfer {
function approve(address token, address spender, uint160 amount, uint48 expiration) external;
}
interface IPositionManager {
function poolManager() external view returns (address);
function permit2() external view returns (address);
function nextTokenId() external view returns (uint256);
function ownerOf(uint256 tokenId) external view returns (address);
function getPositionLiquidity(uint256 tokenId) external view returns (uint128);
function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external payable;
}
/// @notice Custodies the canonical PositionManager NFT under a controller-owner time lock.
/// Liquidity is minted and removed only through the official v4 PositionManager, so the
/// position is represented by the same ERC-721 used by ordinary Uniswap LP flows.
contract MikoLiquidityVault is ReentrancyGuard {
using SafeERC20 for IERC20;
using PoolIdLibrary for PoolKey;
bytes3 private constant MINT_ACTIONS = hex"020d14"; // MINT_POSITION, SETTLE_PAIR, SWEEP
bytes2 private constant BURN_ACTIONS = hex"0311"; // BURN_POSITION, TAKE_PAIR
IPoolManager public immutable poolManager;
IPositionManager public immutable positionManager;
IAllowanceTransfer public immutable permit2;
IERC20 public immutable miko;
IHooks public immutable hook;
uint24 public immutable poolFee;
int24 public immutable tickSpacing;
IControllerOwner public immutable controller;
address public immutable launcher;
uint64 public immutable lockDurationSeconds;
/// @notice PoolId of the canonical PoolKey; its hook clock anchors LP unlock.
bytes32 public immutable canonicalPoolId;
uint64 private _extendedUnlockTimestamp;
uint256 public positionNonce;
mapping(bytes32 indexSalt => uint256 tokenId) public positionTokenId;
event LiquidityAdded(
bytes32 indexed positionSalt,
uint256 indexed tokenId,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 nativeUsed,
uint256 mikoUsed
);
event LiquidityRemoved(
address indexed recipient,
uint256 nativeFromPositions,
uint256 mikoFromPositions,
uint256 nativeSent,
uint256 mikoSent
);
event LockExtended(uint64 previousUnlockTimestamp, uint64 newUnlockTimestamp);
error OnlyControllerOwner();
error OnlyLauncher();
error InvalidConfiguration();
error InvalidLiquidity();
error InvalidPosition();
error LiquidityLocked();
error InvalidRecipient();
error InvalidLockExtension();
error NativeTransferFailed();
constructor(
IPoolManager poolManager_,
IPositionManager positionManager_,
IERC20 miko_,
IHooks hook_,
uint24 poolFee_,
int24 tickSpacing_,
IControllerOwner controller_,
address launcher_,
uint64 lockDurationSeconds_
) {
if (
address(poolManager_).code.length == 0 || address(positionManager_).code.length == 0
|| address(miko_).code.length == 0 || address(hook_) == address(0)
|| tickSpacing_ <= 0 || address(controller_).code.length == 0
|| launcher_ == address(0) || lockDurationSeconds_ == 0
|| block.timestamp > type(uint64).max
|| uint256(lockDurationSeconds_) > type(uint64).max - block.timestamp
) revert InvalidConfiguration();
address permit2_ = positionManager_.permit2();
if (positionManager_.poolManager() != address(poolManager_) || permit2_.code.length == 0) {
revert InvalidConfiguration();
}
poolManager = poolManager_;
positionManager = positionManager_;
permit2 = IAllowanceTransfer(permit2_);
miko = miko_;
hook = hook_;
poolFee = poolFee_;
tickSpacing = tickSpacing_;
controller = controller_;
launcher = launcher_;
lockDurationSeconds = lockDurationSeconds_;
canonicalPoolId = PoolId.unwrap(_poolKey().toId());
}
receive() external payable {}
modifier onlyControllerOwner() {
if (msg.sender != controller.owner()) revert OnlyControllerOwner();
_;
}
modifier onlyLauncher() {
if (msg.sender != launcher) revert OnlyLauncher();
_;
}
function fullRangeTicks() public view returns (int24 tickLower, int24 tickUpper) {
tickLower = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
tickUpper = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
}
function unlockTimestamp() public view returns (uint64) {
address launchHook = address(hook);
if (launchHook.code.length == 0) return 0;
uint64 observedLaunchTimestamp = IMikoLaunchClock(launchHook).launchTimestamp(canonicalPoolId);
if (observedLaunchTimestamp == 0) return 0;
uint256 baseUnlockTimestamp = uint256(observedLaunchTimestamp) + uint256(lockDurationSeconds);
if (baseUnlockTimestamp > type(uint64).max) revert InvalidConfiguration();
uint64 baseUnlock = uint64(baseUnlockTimestamp);
uint64 extendedUnlock = _extendedUnlockTimestamp;
return extendedUnlock > baseUnlock ? extendedUnlock : baseUnlock;
}
/// @notice Mints the one canonical full-range PositionManager NFT. The coordinator
/// initializes the pool immediately before this call in the same transaction.
function addLiquidity(uint128 liquidity, uint256 mikoAmountMax, uint256 deadline)
external
payable
onlyLauncher
nonReentrant
returns (uint256 nativeUsed, uint256 mikoUsed, bytes32 positionSalt)
{
if (
liquidity == 0 || msg.value == 0 || mikoAmountMax == 0 || positionNonce != 0
|| deadline < block.timestamp || deadline > type(uint48).max
|| msg.value > type(uint128).max || mikoAmountMax > type(uint128).max
|| mikoAmountMax > type(uint160).max
) revert InvalidLiquidity();
uint256 nativeBefore = address(this).balance - msg.value;
uint256 mikoBefore = miko.balanceOf(address(this));
if (mikoBefore < mikoAmountMax) revert InvalidLiquidity();
uint256 tokenId = positionManager.nextTokenId();
(int24 tickLower, int24 tickUpper) = fullRangeTicks();
PoolKey memory key = _poolKey();
bytes[] memory params = new bytes[](3);
params[0] = abi.encode(
key,
tickLower,
tickUpper,
uint256(liquidity),
uint128(msg.value),
uint128(mikoAmountMax),
address(this),
bytes("")
);
params[1] = abi.encode(Currency.unwrap(key.currency0), Currency.unwrap(key.currency1));
params[2] = abi.encode(Currency.unwrap(key.currency0), address(this));
address permit2Address = address(permit2);
address positionManagerAddress = address(positionManager);
miko.forceApprove(permit2Address, mikoAmountMax);
permit2.approve(address(miko), positionManagerAddress, uint160(mikoAmountMax), uint48(deadline));
positionManager.modifyLiquidities{value: msg.value}(
abi.encode(abi.encodePacked(MINT_ACTIONS), params), deadline
);
permit2.approve(address(miko), positionManagerAddress, 0, 0);
miko.forceApprove(permit2Address, 0);
if (positionManager.ownerOf(tokenId) != address(this)) revert InvalidPosition();
if (positionManager.getPositionLiquidity(tokenId) != liquidity) revert InvalidPosition();
uint256 nativeAfter = address(this).balance;
uint256 mikoAfter = miko.balanceOf(address(this));
if (nativeAfter > nativeBefore + msg.value || mikoAfter > mikoBefore) revert InvalidPosition();
nativeUsed = nativeBefore + msg.value - nativeAfter;
mikoUsed = mikoBefore - mikoAfter;
if (nativeUsed == 0 || mikoUsed == 0) revert InvalidLiquidity();
positionNonce = 1;
positionTokenId[bytes32(uint256(1))] = tokenId;
positionSalt = bytes32(tokenId);
emit LiquidityAdded(positionSalt, tokenId, tickLower, tickUpper, liquidity, nativeUsed, mikoUsed);
}
function positionLiquidity(bytes32 indexSalt) external view returns (uint128) {
uint256 tokenId = positionTokenId[indexSalt];
return tokenId == 0 ? 0 : positionManager.getPositionLiquidity(tokenId);
}
function extendLock(uint64 newUnlockTimestamp) external onlyControllerOwner {
uint64 previous = unlockTimestamp();
if (previous == 0 || newUnlockTimestamp <= previous) revert InvalidLockExtension();
_extendedUnlockTimestamp = newUnlockTimestamp;
emit LockExtended(previous, newUnlockTimestamp);
}
function removeLiquidity(address to)
external
nonReentrant
onlyControllerOwner
returns (uint256 nativeSent, uint256 mikoSent)
{
if (to == address(0)) revert InvalidRecipient();
uint64 effectiveUnlockTimestamp = unlockTimestamp();
if (effectiveUnlockTimestamp == 0 || block.timestamp < effectiveUnlockTimestamp) {
revert LiquidityLocked();
}
uint256 nativeBefore = address(this).balance;
uint256 mikoBefore = miko.balanceOf(address(this));
uint256 count = positionNonce;
PoolKey memory key = _poolKey();
for (uint256 index = 1; index <= count; ++index) {
bytes32 indexSalt = bytes32(index);
uint256 tokenId = positionTokenId[indexSalt];
if (tokenId == 0) continue;
bytes[] memory params = new bytes[](2);
params[0] = abi.encode(tokenId, uint128(0), uint128(0), bytes(""));
params[1] = abi.encode(
Currency.unwrap(key.currency0), Currency.unwrap(key.currency1), address(this)
);
positionManager.modifyLiquidities(
abi.encode(abi.encodePacked(BURN_ACTIONS), params), block.timestamp
);
positionTokenId[indexSalt] = 0;
}
uint256 nativeAfter = address(this).balance;
uint256 mikoAfter = miko.balanceOf(address(this));
uint256 nativeFromPositions = nativeAfter - nativeBefore;
uint256 mikoFromPositions = mikoAfter - mikoBefore;
mikoSent = mikoAfter;
if (mikoSent != 0) miko.safeTransfer(to, mikoSent);
nativeSent = address(this).balance;
if (nativeSent != 0) {
(bool sent,) = payable(to).call{value: nativeSent}("");
if (!sent) revert NativeTransferFailed();
}
emit LiquidityRemoved(to, nativeFromPositions, mikoFromPositions, nativeSent, mikoSent);
}
function _poolKey() private view returns (PoolKey memory) {
return PoolKey({
currency0: Currency.wrap(address(0)),
currency1: Currency.wrap(address(miko)),
fee: poolFee,
tickSpacing: tickSpacing,
hooks: hook
});
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "poolManager_",
"type": "address",
"internalType": "contract IPoolManager"
},
{
"name": "positionManager_",
"type": "address",
"internalType": "contract IPositionManager"
},
{
"name": "miko_",
"type": "address",
"internalType": "contract IERC20"
},
{
"name": "hook_",
"type": "address",
"internalType": "contract IHooks"
},
{
"name": "poolFee_",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing_",
"type": "int24",
"internalType": "int24"
},
{
"name": "controller_",
"type": "address",
"internalType": "contract IControllerOwner"
},
{
"name": "launcher_",
"type": "address",
"internalType": "address"
},
{
"name": "lockDurationSeconds_",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "nonpayable"
},
{
"name": "InvalidConfiguration",
"type": "error",
"inputs": []
},
{
"name": "InvalidLiquidity",
"type": "error",
"inputs": []
},
{
"name": "InvalidLockExtension",
"type": "error",
"inputs": []
},
{
"name": "InvalidPosition",
"type": "error",
"inputs": []
},
{
"name": "InvalidRecipient",
"type": "error",
"inputs": []
},
{
"name": "LiquidityLocked",
"type": "error",
"inputs": []
},
{
"name": "NativeTransferFailed",
"type": "error",
"inputs": []
},
{
"name": "OnlyControllerOwner",
"type": "error",
"inputs": []
},
{
"name": "OnlyLauncher",
"type": "error",
"inputs": []
},
{
"name": "ReentrancyGuardReentrantCall",
"type": "error",
"inputs": []
},
{
"name": "SafeERC20FailedOperation",
"type": "error",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "LiquidityAdded",
"type": "event",
"inputs": [
{
"name": "positionSalt",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "tokenId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "tickLower",
"type": "int24",
"indexed": false,
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"indexed": false,
"internalType": "int24"
},
{
"name": "liquidity",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "nativeUsed",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "mikoUsed",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "LiquidityRemoved",
"type": "event",
"inputs": [
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "nativeFromPositions",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "mikoFromPositions",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "nativeSent",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "mikoSent",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "LockExtended",
"type": "event",
"inputs": [
{
"name": "previousUnlockTimestamp",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
},
{
"name": "newUnlockTimestamp",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
}
],
"anonymous": false
},
{
"name": "addLiquidity",
"type": "function",
"inputs": [
{
"name": "liquidity",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "mikoAmountMax",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "deadline",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "nativeUsed",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "mikoUsed",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "positionSalt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "payable"
},
{
"name": "canonicalPoolId",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "controller",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IControllerOwner"
}
],
"stateMutability": "view"
},
{
"name": "extendLock",
"type": "function",
"inputs": [
{
"name": "newUnlockTimestamp",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "fullRangeTicks",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "hook",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IHooks"
}
],
"stateMutability": "view"
},
{
"name": "launcher",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "lockDurationSeconds",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "miko",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IERC20"
}
],
"stateMutability": "view"
},
{
"name": "permit2",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IAllowanceTransfer"
}
],
"stateMutability": "view"
},
{
"name": "poolFee",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPoolManager"
}
],
"stateMutability": "view"
},
{
"name": "positionLiquidity",
"type": "function",
"inputs": [
{
"name": "indexSalt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "positionManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPositionManager"
}
],
"stateMutability": "view"
},
{
"name": "positionNonce",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "positionTokenId",
"type": "function",
"inputs": [
{
"name": "indexSalt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "tokenId",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "removeLiquidity",
"type": "function",
"inputs": [
{
"name": "to",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "nativeSent",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "mikoSent",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "tickSpacing",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "unlockTimestamp",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"type": "receive",
"stateMutability": "payable"
}
]0x608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c908163089fe6aa146114de5750806312261ee71461149b57806316eebd1e1461145857806318beb3d51461141e578063607f1402146113f4578063791b98bc146113b15780637f5a7c7b1461136e5780638529f0d614611342578063859e6d6a146112135780639679c1891461090357806397bd1017146108e557806399dfad3b146108a1578063aa082a9d14610874578063d0c93a7c14610836578063d798f86e14610293578063dc4c90d31461024f578063ee9e652014610180578063ef07b9ec1461013b5763f77c47910361000f573461013857806003193601126101385760206040516001600160a01b037f0000000000000000000000003613174ddc40251a450705c4511ee691edb2eb63168152f35b80fd5b5034610138578060031936011261013857602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000008cbd168152f35b503461013857602036600319011261013857600435815260036020526040812054806101bc57506020905b6001600160801b0360405191168152f35b60405190631efeed3360e01b825260048201526020816024816001600160a01b037f00000000000000000000000058daec3116aae6d93017baaea7749052e8a04fa7165afa9081156102445760209291610217575b506101ab565b6102379150823d841161023d575b61022f81836115c5565b810190611706565b5f610211565b503d610225565b6040513d84823e3d90fd5b503461013857806003193601126101385760206040516001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951168152f35b5034610138576020366003190112610138576001600160a01b036004351660043503610138576102c161188d565b604051638da5cb5b60e01b81526020816004817f0000000000000000000000003613174ddc40251a450705c4511ee691edb2eb636001600160a01b03165afa8015610244576001600160a01b03918391610807575b501633036107f8576001600160a01b0360043516156107e95767ffffffffffffffff610340611732565b1680159081156107df575b506107d0576040516370a0823160e01b81523060048201527f000000000000000000000000a0158ca85e184da205657ba3032864b409fcdd979047906020816024816001600160a01b0387165afa9081156107c5578491610793575b50600254906103b46118ab565b6020929060015b828111156105705750506040516370a0823160e01b81523060048201529390504783856024816001600160a01b038a165afa948515610565578795610530575b506104109161040991611606565b9184611606565b93836104ec575b50479384610477575b9460019160409687519182528482015285878201528460608201527f8598e6b147330d38243f9c4cd33d61e208b9015719e977086fa42a0f73b1462b60806001600160a01b036004351692a2558351928352820152f35b85808080886001600160a01b03600435165af13d156104e7573d67ffffffffffffffff81116104d357604051906104b7601f8201601f19168701836115c5565b815287853d92013e5b61042057633d2cec6f60e21b8652600486fd5b634e487b7160e01b88526041600452602488fd5b6104c0565b60405163a9059cbb60e01b848201526004356001600160a01b031660248201526044808201869052815261052a916105256064836115c5565b611995565b5f610417565b9094508381813d831161055e575b61054881836115c5565b8101031261055a5751936104106103fb565b5f80fd5b503d61053e565b6040513d89823e3d90fd5b808852600385526040882054801561078d576040519061059687600260051b01836115c5565b6002825290899187835b6020820181106107665750506105f7604051916105bd8a846115c5565b8483526105e96040519384928c84015286604084015286606084015260808084015260a0830190611613565b03601f1981018352826115c5565b61060082611637565b5261060a81611637565b506001600160a01b038451166001600160a01b0360208601511660405191898301526040820152306060820152606081526106466080826115c5565b61064f82611658565b5261065981611658565b5060405161031160f01b888201526002815261068b9061067a6022826115c5565b6105e96040519384928b8401611678565b6001600160a01b037f00000000000000000000000058daec3116aae6d93017baaea7749052e8a04fa7163b1561076257816106dc916040518093819263dd46508f60e01b83524290600484016116ea565b0381836001600160a01b037f00000000000000000000000058daec3116aae6d93017baaea7749052e8a04fa7165af1801561024457610749575b50819052600385528760408120555b5f198114610735576001016103bb565b634e487b7160e01b88526011600452602488fd5b81610753916115c5565b61075e57875f610716565b8780fd5b5080fd5b60608482018301528c94508991016105a0565b634e487b7160e01b5f52604160045260245ffd5b50610725565b90506020813d6020116107bd575b816107ae602093836115c5565b8101031261055a57515f6103a7565b3d91506107a1565b6040513d86823e3d90fd5b6347a73ad960e11b8152600490fd5b905042105f61034b565b634e46966960e11b8152600490fd5b632a4596db60e11b8152600490fd5b610829915060203d60201161082f575b61082181836115c5565b8101906115e7565b5f610316565b503d610817565b503461013857806003193601126101385760206040517f000000000000000000000000000000000000000000000000000000000000003c60020b8152f35b5034610138578060031936011261013857602061088f611732565b67ffffffffffffffff60405191168152f35b503461013857806003193601126101385760206040516001600160a01b037f000000000000000000000000a0158ca85e184da205657ba3032864b409fcdd97168152f35b50346101385780600319360112610138576020600254604051908152f35b50606036600319011261055a576004356001600160801b03811680910361055a576024356044356001600160a01b037f000000000000000000000000d267eea2524adcecf73dade4df70037f246944fa1633036112045761096261188d565b821580156111fc575b80156111f4575b80156111e9575b80156111e0575b80156111d1575b80156111c1575b80156111b1575b80156111a1575b61115e576109aa3447611606565b6040516370a0823160e01b81523060048201529390927f000000000000000000000000a0158ca85e184da205657ba3032864b409fcdd97916001600160a01b038316602087602481845afa9687156110ad575f9761116d575b5082871061115e57604051631d5e528f60e21b8152957f00000000000000000000000058daec3116aae6d93017baaea7749052e8a04fa76001600160a01b0316602088600481845afa9788156110ad575f9861112a575b50610a63611546565b959096610a6e6118ab565b986040516080610a7e81836115c5565b60038252601f19015f5b8181106111195750506040519a60209a610aa28c8e6115c5565b5f8d5260405182516001600160a01b03168d820152808d84019283516001600160a01b03166040830152604085015162ffffff166060830152606085015160020b608083015260808501516001600160a01b031660a083015260020b9c8d60c083015260020b9e8f60e08301528c610100830152346001600160801b03166101208301526001600160801b03891661014083015230610160830152610180820161018090526101a08201610b5591611613565b03601f1981018252610b6790826115c5565b610b7084611637565b52610b7a83611637565b508b82516001600160a01b031691516001600160a01b031691604051928392830191610bbd929092916001600160a01b0360209181604085019616845216910152565b03601f1981018252610bcf90826115c5565b610bd883611658565b52610be282611658565b5051604080516001600160a01b039092168c830190815230602082015282910103601f1981018252610c1490826115c5565b610c1d82611668565b52610c2781611668565b5060405163095ea7b360e01b8b82019081527f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba36001600160a01b031660248301819052604480840188905283529591908c908690610c866064856115c5565b8351905a5f938491f15f513d826110fd575b5050156110b8575b50843b1561055a576001600160a01b03604051916387517c4560e01b835289600484015287602484015216604482015265ffffffffffff831660648201525f8160848183895af180156110ad57611096575b50908d91610d278b6105e96040519361834560ea1b8386015260038552610d1a6023866115c5565b6040519485938401611678565b853b156110925760405163dd46508f60e01b815291839183918291610d509190600484016116ea565b038134895af180156102445761107d575b5050813b15611079578b6040516387517c4560e01b8152866004820152846024820152816044820152816064820152818160848183885af1801561024457611064575b505060405163095ea7b360e01b8982019081526024820184905260448083018f905282529091908d908a908290610ddc6064876115c5565b85519082865af181513d82611048575b505015611008575b505050506040516331a9108f60e11b81528860048201528681602481855afa908115610ffd578b91610fe0575b506001600160a01b0330911603610f62578560249160405192838092631efeed3360e01b82528c60048301525afa908115610fa95784916001600160801b03918c91610fc3575b501603610fb45790602491854792604051948580926370a0823160e01b82523060048301525afa928315610fa9578a93610f7a575b50610ea83482611725565b82118015610f71575b610f6257610ed39291610ec8610ecd923490611725565b611606565b97611606565b9386158015610f5a575b610f4b57857f0d43f86a16599b7f82fb3112a3f5ac52ad996e7284befbbe83300f56ce82424360a060019560609b9584958860025588885260038a528560408920556040519283528983015260408201528a8c820152886080820152a3556040519384528301526040820152f35b631fff968160e01b8852600488fd5b508415610edd565b63673f032f60e11b8a5260048afd5b50888311610eb1565b9092508581813d8311610fa2575b610f9281836115c5565b8101031261055a5751915f610e9d565b503d610f88565b6040513d8c823e3d90fd5b63673f032f60e11b8952600489fd5b610fda9150883d8a1161023d5761022f81836115c5565b5f610e68565b610ff79150873d891161082f5761082181836115c5565b5f610e21565b6040513d8d823e3d90fd5b61103f93610525916040519163095ea7b360e01b8d84015260248301526044820152604481526110396064826115c5565b82611995565b5f80808c610df4565b90915061105c5750863b15155b5f80610dec565b600114611055565b8161106e916115c5565b611079578b5f610da4565b8b80fd5b81611087916115c5565b611079578b5f610d61565b8280fd5b6110a491929e505f906115c5565b5f9c905f610cf2565b6040513d5f823e3d90fd5b6110f7906110f18d6040519063095ea7b360e01b908201528860248201525f6044820152604481526110eb6064826115c5565b87611995565b85611995565b5f610ca0565b9091506111115750883b15155b5f80610c98565b60011461110a565b806060602080938601015201610a88565b9097506020813d602011611156575b81611146602093836115c5565b8101031261055a5751965f610a5a565b3d9150611139565b631fff968160e01b5f5260045ffd5b9096506020813d602011611199575b81611189602093836115c5565b8101031261055a5751955f610a03565b3d915061117c565b506001600160a01b03821161099c565b506001600160801b038211610995565b506001600160801b03341161098e565b5065ffffffffffff8111610987565b50428110610980565b506002541515610979565b508115610972565b50341561096b565b6304e255a160e01b5f5260045ffd5b3461055a57602036600319011261055a5760043567ffffffffffffffff811680910361055a57604051638da5cb5b60e01b81526020816004817f0000000000000000000000003613174ddc40251a450705c4511ee691edb2eb636001600160a01b03165afa80156110ad576001600160a01b03915f91611323575b501633036113145767ffffffffffffffff6112a7611732565b16908115801561130a575b6112fb577f24244521d46a55ce4a7e120862e4ed512a50b1bf94cfb78c55b9c1ce49cac96b918160409267ffffffffffffffff19600154161760015582519182526020820152a1005b637828530360e11b5f5260045ffd5b50818111156112b2565b632a4596db60e11b5f5260045ffd5b61133c915060203d60201161082f5761082181836115c5565b8361128e565b3461055a575f36600319011261055a57604061135c611546565b82519160020b825260020b6020820152f35b3461055a575f36600319011261055a5760206040516001600160a01b037f0000000000000000000000000a790b185f5f3f4bf6ecae95bf3f275ea5ff60cc168152f35b3461055a575f36600319011261055a5760206040516001600160a01b037f00000000000000000000000058daec3116aae6d93017baaea7749052e8a04fa7168152f35b3461055a57602036600319011261055a576004355f526003602052602060405f2054604051908152f35b3461055a575f36600319011261055a5760206040517f553c08e0ec57a1a1ef4a093bb896adff494c8ea525e885995978e9bc944717708152f35b3461055a575f36600319011261055a5760206040516001600160a01b037f000000000000000000000000d267eea2524adcecf73dade4df70037f246944fa168152f35b3461055a575f36600319011261055a5760206040516001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3168152f35b3461055a575f36600319011261055a5760209062ffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b9060020b9060020b02908160020b91820361153257565b634e487b7160e01b5f52601160045260245ffd5b7f000000000000000000000000000000000000000000000000000000000000003c908160020b91821561159557611592906115878185620d89e7190561151b565b93620d89e80561151b565b90565b634e487b7160e01b5f52601260045260245ffd5b60a0810190811067ffffffffffffffff82111761077957604052565b90601f8019910116810190811067ffffffffffffffff82111761077957604052565b9081602091031261055a57516001600160a01b038116810361055a5790565b9190820391821161153257565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b8051156116445760200190565b634e487b7160e01b5f52603260045260245ffd5b8051600110156116445760400190565b8051600210156116445760600190565b9061168b90604083526040830190611613565b906020818303910152815180825260208201916020808360051b8301019401925f915b8383106116bd57505050505090565b90919293946020806116db600193601f198682030187528951611613565b970193019301919392906116ae565b929190611701602091604086526040860190611613565b930152565b9081602091031261055a57516001600160801b038116810361055a5790565b9190820180921161153257565b6001600160a01b037f0000000000000000000000000a790b185f5f3f4bf6ecae95bf3f275ea5ff60cc16803b1561183d5760206024916040519283809263dcef319360e01b82527f553c08e0ec57a1a1ef4a093bb896adff494c8ea525e885995978e9bc9447177060048301525afa80156110ad575f90611842575b67ffffffffffffffff915016801561183d576117f59067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000008cbd1690611725565b67ffffffffffffffff811161182e5767ffffffffffffffff1667ffffffffffffffff60015416908082115f14611829575090565b905090565b63c52a9bd360e01b5f5260045ffd5b505f90565b506020813d602011611885575b8161185c602093836115c5565b8101031261055a575167ffffffffffffffff8116810361055a5767ffffffffffffffff906117ae565b3d915061184f565b60025f541461189c5760025f55565b633ee5aeb560e01b5f5260045ffd5b5f60806040516118ba816115a9565b82815282602082015282604082015282606082015201526040516118dd816115a9565b5f81526001600160a01b037f000000000000000000000000a0158ca85e184da205657ba3032864b409fcdd9716602082015262ffffff7f00000000000000000000000000000000000000000000000000000000000000001660408201527f000000000000000000000000000000000000000000000000000000000000003c60020b60608201526001600160a01b037f0000000000000000000000000a790b185f5f3f4bf6ecae95bf3f275ea5ff60cc16608082015290565b905f602091828151910182855af1156110ad575f513d6119e057506001600160a01b0381163b155b6119c45750565b6001600160a01b0390635274afe760e01b5f521660045260245ffd5b600114156119bd56fea26469706673582212201ccbe2e2611cee791ed60bc6acc2ce86d0556b305bb435c5fbde32083420a53064736f6c634300081a0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0xb8c2d8…21d10a | 18 days agoThu, 30 Jul 2026 17:36:51 UTC | 0x8598e6…462b | [0] 0x000000000000…457068e1 data: 0x000000000000000000…3be56141 |
| 0xcc1bf5…b965bf | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0x0d43f8…4243 | [0] 0x000000000000…0005cfa3 [1] 0x000000000000…0005cfa3 data: 0xffffffffffffffffff…e5ffa67f |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0xb8c2d8…21d10a | removeLiquidity | 23,499,924 | 18 days agoThu, 30 Jul 2026 17:36:51 UTC | 0x34a7…68e1 | IN | MikoLiquidityVault | $0.000 ETH | 0.00000595 |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0xcc1bf5…b965bf | CALL | 0x5a8b3ce9 | 0x58da…4fa7 | IN | 0xc855…b77f | 0.00000 ETH |
| 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0xcc1bf5…b965bf | CALL | 0x5a8b3ce9 | 0xc855…b77f | OUT | 0x58da…4fa7 | 0.5 ETH |
| 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0xcc1bf5…b965bf | CALL | 0x5a8b3ce9 | 0xd267…44fa | IN | 0xc855…b77f | 0.5 ETH |
| 21,198,283 | 20 days agoTue, 28 Jul 2026 01:29:33 UTC | 0x75a644…f6d27f | CREATE | deployCreate3 | 0xd1f2…5355 | IN | 0xc855…b77f | 0 ETH |
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0xb8c2d86e…21d10a | Transfer | 23,499,924 | 18 days agoThu, 30 Jul 2026 17:36:51 UTC | 0xc855…b77f | OUT | 0x34a7…68e1 | 549,861,044.297830 MTEST1 | M1_TEST (MTEST1) | |
| 0xb8c2d86e…21d10a | Transfer | 23,499,924 | 18 days agoThu, 30 Jul 2026 17:36:51 UTC | 0x8366…0951 | IN | 0xc855…b77f | 549,861,044.297830 MTEST1 | M1_TEST (MTEST1) | |
| 0xcc1bf5fb…b965bf | Transfer | 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0xc855…b77f | OUT | 0x8366…0951 | 549,999,999.999999 MTEST1 | M1_TEST (MTEST1) | |
| 0xcc1bf5fb…b965bf | Transfer | 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0x34a7…68e1 | IN | 0xc855…b77f | 549,999,999.999999 MTEST1 | M1_TEST (MTEST1) |
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| 0xb8c2d86e…21d10a | Transfer | 23,499,924 | 18 days agoThu, 30 Jul 2026 17:36:51 UTC | 0xc855…b77f | OUT | 0x0000…0000 | Transfer | Uniswap v4 Positions NFT (UNI-V4-POSM) #380835 | |
| 0xcc1bf5fb…b965bf | Transfer | 21,249,942 | 20 days agoTue, 28 Jul 2026 02:55:53 UTC | 0x0000…0000 | IN | 0xc855…b77f | Mint | Uniswap v4 Positions NFT (UNI-V4-POSM) #380835 |