Skip to content

Integrate Titan Locker Into Your Contracts & dApp

Developer guide: contract addresses, ABIs, and how to call createTokenLock and createVestingLock, read lock data, and verify a lock on Robinhood Chain.

Updated 8 min read

You can integrate Titan Locker directly from your own contracts or dApp on Robinhood Chain (chain ID 4663). Approve your token to the TitanLockerManagerV2_1 contract, then call createTokenLock or createVestingLock; the manager deploys an isolated lock contract and emits an event with the new lock id. Everything is readable on-chain, so integrators can verify locks without an API.

Addresses (Robinhood Chain, 4663)

TitanLockerManagerV2_1View on Etherscan

Create new token locks, LP locks, vesting, and V3/V4 position locks - audit-fixed.

0x102a70bDA2C833b3483A2eE55C14c7ea0fb7A01B

Fee-calculation library linked into V2_1.

0xFBfa1ce526f98deC2251D44d1DaF7c599223aFe6

Create a token lock

Approve the token to the manager, then call createTokenLock(token, amount, unlockTime, maxTokenFeeBps). Pass the flat ETH fee as msg.value, or send 0 to pay the fee in-kind from the token. maxTokenFeeBps reverts the call if the live fee exceeds what you expected - pass the value you just read from tokenFeeBps() (or the contract's own 500 bps / 5% hard cap) rather than a hardcoded guess.

solidity
// Solidity — lock tokens from your own contract
interface ITitanLockerManagerV2_1 {
    function createTokenLock(address token, uint256 amount, uint40 unlockTime, uint16 maxTokenFeeBps) external payable;
    function ethFee() external view returns (uint256);
    function tokenFeeBps() external view returns (uint16);
}

IERC20(token).approve(MANAGER_V2_1, amount);
ITitanLockerManagerV2_1 manager = ITitanLockerManagerV2_1(MANAGER_V2_1);
uint256 fee = manager.ethFee();
uint16 maxFeeBps = manager.tokenFeeBps();
manager.createTokenLock{value: fee}(token, amount, unlockTime, maxFeeBps);

Create a vesting lock

Call createVestingLock(token, amount, start, cliff, end, maxTokenFeeBps) with start < end and start <= cliff <= end. The grant releases linearly to the lock owner via release().

solidity
manager.createVestingLock{value: fee}(
    token, amount, start, cliff, end, maxFeeBps
);

Read a lock from a dApp (viem)

typescript
import { createPublicClient, http } from "viem";

const client = createPublicClient({
  chain: { id: 4663, name: "Robinhood Chain", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } } },
  transport: http(),
});

const count = await client.readContract({
  address: "0x26b0654a0756dcd036d4e7215324f3d2be34d79e",
  abi: managerV2Abi,
  functionName: "tokenLockerCount",
});

Public locker API (read-only, free)

If you'd rather not read the chain yourself, https://api.titandeployer.com serves the same indexed lock data the Titan Locker site uses: every manager on Robinhood Chain (plus the retired Stable Chain deployment), merged and kept in sync with the chain. It is free, read-only, and needs no key. It is rate-limited, so cache responses and don't poll faster than you need. The contracts stay the source of truth: the API is a convenience index of on-chain state, and every lock it returns can be checked on the explorer.

EndpointReturns
GET /v1/chainsIndexed chains, every manager address and deploy block, and sync status.
GET /v1/stats?chainId=4663Aggregate counts and priced active value for one chain (the numbers on /locker).
GET /v1/locks?chainId=4663&limit=100Locks on one chain, newest first, with a cursor for paging.
GET /v1/locks/{chainId}/{version}/{id}One lock (version: v1, v2, v2_1, v2_1_titan).
GET /v1/addresses/{address}/locks?chainId=4663Every lock that touches an address: as token, pair token, owner, or creator.
GET /v1/search?q=…Search by lock id, token, LP pair, or wallet.

For a stable, documented aggregate, https://titanlocker.com/api/public/locker/stats returns the same statistics as /locker, with a schemaVersion field and a link to the methodology.

Check every manager, not just the newest

New locks are created on TitanLockerManagerV2_1, but TitanLockerManagerV2 (its pre-audit-fix predecessor) and the original TitanLockerManagerV1 are both still deployed and each still holds real, active locks created before the next generation shipped. A fourth manager, the Titan Vault, holds the permanently locked liquidity of every token launched on Titan.fun. An integration that only reads the newest manager will silently miss legitimate, still-active locks on the others. Query every manager and merge the results, exactly as Titan Locker's own frontend does.

TitanLockerManagerV1 (legacy)View on Etherscan

Existing locks created before V2 - still fully readable and withdrawable.

0x713E56CeE7060F01F710bF26Aff988264dcfb311
TitanLockerManagerV2 (legacy)View on Etherscan

Locks created before the ContractWolf audit fix - still fully readable and withdrawable.

0x26b0654a0756dcd036d4e7215324f3d2be34d79e
TitanLockerManagerV2_1 (current)View on Etherscan

All new token locks, LP locks, vesting, and V3/V4 position locks.

0x102a70bDA2C833b3483A2eE55C14c7ea0fb7A01B
Titan Vault (Titan.fun launch locks)View on Etherscan

Same V2.1 code and ABI, with its own lock-id space. Holds every Titan.fun launch's Uniswap V3 position on a rolling 100-year lock.

0x4E907349FA31f9e42F0bf0E2E2fd09e6E1E2dB9d

Stable Chain (retired for Titan Locker on 9 October 2026) has two managers holding existing, read-only locks: TitanLockerManagerV2_1 at the same address as on Robinhood Chain, and its own Titan Vault at 0xc44cE9f3E9c7F34CAE0f7418979e70565DbE4b1d. Each vault has its own id space, so always qualify a vault lock by chain.

Look up every lock for a token, LP pair, or wallet

Every manager indexes every lock by every address that matters to it - the locked token (or, for a Uniswap V3/V4 position, its position manager), the lock's own contract address, the lock owner, and for LP/position locks, the pair's underlying token0/token1. Calling getTokenLockersForAddress(address) on any manager returns every lock id touching that address, with no separate indexer required.

typescript
interface ITitanLockerManager {
    function getTokenLockersForAddress(address addr) external view returns (uint40[] memory);
    function getTokenLockData(uint40 id) external view returns (
        bool isLpToken, uint40 id, address contractAddress, address lockOwner,
        address token, address createdBy, uint40 createdAt, uint40 unlockTime,
        uint256 balance, uint256 totalSupply
    ); // V1 shape - V2/V2_1's getTokenLockData additionally reports LockKind and tokenId; see the ABI.
}

const [v1Ids, v2Ids, v2_1Ids] = await Promise.all([
  client.readContract({ address: "0x713E56CeE7060F01F710bF26Aff988264dcfb311", abi: managerV1Abi, functionName: "getTokenLockersForAddress", args: [tokenAddress] }),
  client.readContract({ address: "0x26b0654a0756dcd036d4e7215324f3d2be34d79e", abi: managerV2Abi, functionName: "getTokenLockersForAddress", args: [tokenAddress] }),
  client.readContract({ address: "0x102a70bDA2C833b3483A2eE55C14c7ea0fb7A01B", abi: managerV2Abi, functionName: "getTokenLockersForAddress", args: [tokenAddress] }),
]);

const locks = await Promise.all([
  ...v1Ids.map((id) => client.readContract({ address: "0x713E56CeE7060F01F710bF26Aff988264dcfb311", abi: managerV1Abi, functionName: "getTokenLockData", args: [id] })),
  ...v2Ids.map((id) => client.readContract({ address: "0x26b0654a0756dcd036d4e7215324f3d2be34d79e", abi: managerV2Abi, functionName: "getTokenLockData", args: [id] })),
  ...v2_1Ids.map((id) => client.readContract({ address: "0x102a70bDA2C833b3483A2eE55C14c7ea0fb7A01B", abi: managerV2Abi, functionName: "getTokenLockData", args: [id] })),
]);

Calculating a percentage of supply locked (fungible locks only)

For a plain ERC-20 or LP token lock, sum the balance field across every matching lock for that token, then divide by IERC20(token).totalSupply(). This is meaningful only for fungible balance-based locks - a Uniswap V3/V4 position lock holds an NFT, not a token quantity, so it has no balance to include in this calculation and no valid "percentage locked" figure. Don't combine position locks into a token-supply percentage; state their lock status separately.

How explorers can verify and display a Titan Locker lock

A block explorer already has everything needed to show "this address is a Titan Locker lock": each lock contract is deployed by one of the manager addresses above, and its own getLockData()/getTokenLockData() view function (available on the lock contract itself, not just the manager) returns its kind, owner, asset, and unlock time with no extra lookups. Cross-reference the deploying manager to confirm it's a genuine Titan Locker child contract rather than an unrelated contract with a similarly-named function.

How wallets can show lock status for a held token or position

A wallet already knows the tokens and NFTs an address holds. To additionally flag "this token has locks" or "this position is locked," call getTokenLockersForAddress on every manager with the token's (or position manager's) address - a non-empty result means locks exist for that asset, and getTokenLockData on each id gives the amount, owner, and unlock time to display inline.

How analytics platforms can display lock status

The same getTokenLockersForAddress + getTokenLockData pattern above is exactly what an analytics platform needs to show a project's locked supply, upcoming unlock dates, or vesting schedule progress (via getVesting() and vestedAmount() on a vesting lock's own contract) - all without needing to run any Titan Locker-specific infrastructure, just an RPC connection to Robinhood Chain. Two platforms already do this: DefiLlama tracks Titan Locker's TVL and lock-fee revenue with its own open-source adapters, and Quick Intel's token scanner recognises liquidity held in Titan Locker as locked.

How exchanges can verify locked liquidity before listing

Apply the same token-address lookup to the LP token (or, for a Uniswap V3/V4 pool, to the position manager plus the pool's real underlying tokens) a project claims to have locked. Confirm the reported balance and unlock time directly from getTokenLockData rather than trusting a submitted screenshot or link - the on-chain data is the actual lock, not a claim about one.

Displaying a lock badge or certificate

The simplest integration is linking directly to the lock's own certificate page, which already reads and displays everything above without any integration work at all. Each certificate also has a public, unauthenticated PNG at its own /opengraph-image path (for example https://titanlocker.com/lock/120/opengraph-image) showing the same data as an image, embeddable directly with a plain <img> tag for a live-updating lock badge.

ManagerRobinhood Chain certificateStable Chain certificate (retired, read-only)
TitanLockerManagerV2_1 (current)https://titanlocker.com/lock/{id}https://titanlocker.com/lock/stable/{id}
Titan Vault (Titan.fun launches)https://titanlocker.com/lock/titan/{id}https://titanlocker.com/lock/stable/titan/{id}
TitanLockerManagerV2 (legacy)https://titanlocker.com/lock/v2/{id}Not deployed
TitanLockerManagerV1 (legacy)https://titanlocker.com/lock/v1/{id}Not deployed

Security considerations for integrators

  • Always verify which manager (V1, V2, V2_1, or a Titan Vault) deployed a lock contract before trusting its data - lock ids repeat across managers, so a lock is identified by manager plus id, not id alone.
  • A lock contract's own address is the source of truth; don't reconstruct or guess a lock's address instead of reading it from getTokenLockAddress/getTokenLockData.
  • Treat a Uniswap V3/V4 position lock's balance as always zero and meaningless - check kind first, and read the position's underlying pair via the lock's own getUnderlyingTokens() rather than assuming it holds an ERC-20 balance.
  • Confirm the lock contract's source is verified on Etherscan before trusting a value-moving integration (e.g. a listing decision) that depends on it.