For Developers & AI Agents
Machine-readable reference · Updated September 2026
What 0xKeep is
An immutable, non-custodial smart contract that time-locks ERC-20 tokens (including Uniswap v2 and Aerodrome classic LP tokens) and runs linear vesting schedules with an optional cliff. No owner, no admin, no pause, no proxy. It does not lock NFT liquidity positions (Uniswap v3/v4). Not audited by a third party; see the security page.
Contracts
| Chain | ID | Address | Lock / vest fee |
|---|---|---|---|
| Base | 8453 | 0x048d1326B3b0531A5d043984F4e495285B07af4B | 0 / 0 ETH |
| Arbitrum One | 42161 | 0xDC9bFb15C28486590Cbf58F3FEA9ADbEB9B0334c | 0.03 / 0.02 ETH |
| Optimism | 10 | 0x1Ecf87D69c4a5c8D10ffb7D73e8ABB415043f866 | 0.03 / 0.02 ETH |
ABI: /abi/ZeroXKeepLocker.json. Source verified on Sourcify (repo.sourcify.dev/<chainId>/<address>). Read LOCK_FEE() and VESTING_FEE() from the contract instead of hardcoding them.
Check a lock (read-only JSON API)
No key, no wallet. Open CORS, cached about 30 seconds.
GET https://app.0x-keep.xyz/api/lock/0xK-BL-0
GET https://app.0x-keep.xyz/api/vesting/0xK-BV-0
Lock responses include status (locked | unlocked | withdrawn), token address, symbol and decimals, amount, owner, unlock time (unix and ISO), and contract and explorer links. Vesting responses add total, claimed, vestedNow, claimableNow and the schedule (start, cliff end, end).
ID format: 0xK-{chain}{type}-{n}. Chain: B Base, A Arbitrum, O Optimism. Type: L lock, V vesting. n is the on-chain index used by locks(n) and vestings(n). Errors return {"error": "..."} with status 400 (bad ID), 404 (not found) or 502 (RPC problem).
For security scanners: all locks for a token
One call returns every active 0xKeep lock and vesting schedule for a token, the share of supply locked, and a locked_detail block in the GoPlus Token Security format.
GET https://app.0x-keep.xyz/api/token/{chainId}/{tokenAddress}
e.g. https://app.0x-keep.xyz/api/token/8453/0x4200000000000000000000000000000000000006
Full integration notes (events, state reads, guarantees): INTEGRATIONS.md.
Read directly from the contract
allLocksCount() returns uint256
locks(uint256 id) returns (token, amount uint96, owner, decimals uint8,
withdrawn bool, unlockTime uint32, id)
getUserLocks(address owner) returns uint256[]
allVestingsCount() returns uint256
vestings(uint256 id) returns (token, totalAmount uint96, owner, decimals uint8,
claimedAmount uint96, startTime uint32,
cliffDuration uint32, duration uint32, id)
getUserVestings(address owner) returns uint256[]
A lock can be withdrawn by its owner when block.timestamp >= unlockTime and withdrawn is false. Vesting releases linearly from startTime + cliffDuration over duration seconds.
Create a lock or vesting schedule
Lock:
1. token.approve(LOCKER, amount)
2. LOCKER.lockToken(token, amount, unlockTime) // payable, send LOCK_FEE()
emits Locked(lockId, token, owner, amount, unlockTime, chainId)
Vesting:
1. token.approve(LOCKER, amount)
2. LOCKER.createVesting(token, amount, cliffSeconds, durationSeconds) // payable, send VESTING_FEE()
emits VestingCreated(vestingId, token, owner, amount, cliff, duration, chainId)
Contract limits: amount above 0 and within uint96; unlock time in the future and under 100 years away; vesting duration at least 1 day; cliff under 10 years. Fee-on-transfer tokens are recorded at the amount actually received. Rebasing tokens are not supported. Other owner actions: extendLock, transferLockOwnership, withdrawLock, claimVesting, transferVestingOwnership.
Plain-text version
The same information for language models: /llms.txt.