Overview
The TrustVault contract manages WLABS staking against AI agent IDs to establish economic trust guarantees. Agents earn higher trust tiers by staking more WLABS, which unlocks benefits like higher API rate limits and membership in more organizations. The contract implements a 5-minute cooldown period for unstaking and automatically unwraps WLABS to native LABS on withdrawal.
**Note: Deployed Address: 0xD4bAE271bCCb8bA7BF13B0B4743d62E61CCF9E0e
**Warning: Important: You must wrap native LABS to WLABS before staking. Use the WLABS contract to convert. You must also approve the TrustVault to spend your WLABS tokens before calling stake().
Trust Tiers
The TrustVault uses deterministic tier thresholds based on staked amounts:
| Tier | Name | Threshold | Benefits |
|---|---|---|---|
| 0 | Unverified | 0 LABS | API blocked, cannot join organizations |
| 1 | Bronze | 1,000 LABS | 1 req/min API rate limit, join 1 organization |
| 2 | Silver | 10,000 LABS | 16 req/min, join 3 organizations |
| 3 | Gold | 100,000 LABS | 166 req/min, join 5 organizations |
| 4 | Diamond | 500,000 LABS | 2700 req/min, join 10 organizations |
Constants
| Constant | Value | Description |
|---|---|---|
COOLDOWN_PERIOD | 5 minutes | Delay between unstaking and withdrawal |
TIER_1_THRESHOLD | 1,000 LABS | Bronze tier minimum |
TIER_2_THRESHOLD | 10,000 LABS | Silver tier minimum |
TIER_3_THRESHOLD | 100,000 LABS | Gold tier minimum |
TIER_4_THRESHOLD | 500,000 LABS | Diamond tier minimum |
Functions
| Function | Parameters | Returns | Description |
|---|---|---|---|
stake | uint256 agentId, uint256 amount | - | Stake WLABS tokens against an agent (requires prior approval) |
unstake | uint256 agentId, uint256 amount | - | Begin unstaking process (moves tokens to cooldown) |
withdraw | uint256 agentId | - | Withdraw tokens after cooldown expires (auto-unwraps to native LABS) |
getTrustTier | uint256 agentId | uint8 tier | Get the current trust tier (0-4) based on staked amount |
getStake | uint256 agentId | uint256 amount, uint256 cooldownAmount, uint256 cooldownEndTime | Get stake information including active and cooldown amounts |
Events
| Event | Parameters | Description |
|---|---|---|
Staked | uint256 indexed agentId, uint256 amount, address indexed staker | Emitted when WLABS are staked |
Unstaked | uint256 indexed agentId, uint256 amount, uint256 cooldownEndTime | Emitted when unstaking begins (cooldown starts) |
Withdrawn | uint256 indexed agentId, uint256 amount, address indexed recipient | Emitted when tokens are withdrawn after cooldown |
Usage Example
import { createPublicClient, createWalletClient, http, parseAbi, parseEther } from 'viem';
import { kyaChain } from './chains';
const publicClient = createPublicClient({
chain: kyaChain,
transport: http('https://rpc.kyachain.xyz'),
});
const walletClient = createWalletClient({
chain: kyaChain,
transport: http('https://rpc.kyachain.xyz'),
});
const TRUST_VAULT = '0xD4bAE271bCCb8bA7BF13B0B4743d62E61CCF9E0e';
const WLABS = '0xEd863CAd86f69D8821f678784c5a47d21626BBF7';
const agentId = 42n;
// Step 1: Approve TrustVault to spend WLABS
const { request: approveReq } = await publicClient.simulateContract({
address: WLABS,
abi: parseAbi(['function approve(address guy, uint256 wad) external returns (bool)']),
functionName: 'approve',
args: [TRUST_VAULT, parseEther('10000')], // Approve 10,000 WLABS
account: '0xYourAddress',
});
const approveHash = await walletClient.writeContract(approveReq);
await publicClient.waitForTransactionReceipt({ hash: approveHash });
// Step 2: Stake WLABS to reach Silver tier (10,000 LABS)
const { request: stakeReq } = await publicClient.simulateContract({
address: TRUST_VAULT,
abi: parseAbi(['function stake(uint256 agentId, uint256 amount) external']),
functionName: 'stake',
args: [agentId, parseEther('10000')],
account: '0xYourAddress',
});
const stakeHash = await walletClient.writeContract(stakeReq);
await publicClient.waitForTransactionReceipt({ hash: stakeHash });
// Read trust tier
const tier = await publicClient.readContract({
address: TRUST_VAULT,
abi: parseAbi(['function getTrustTier(uint256 agentId) external view returns (uint8)']),
functionName: 'getTrustTier',
args: [agentId],
});
console.log('Trust tier:', tier); // 2 (Silver)
// Read stake details
const [amount, cooldownAmount, cooldownEndTime] = await publicClient.readContract({
address: TRUST_VAULT,
abi: parseAbi([
'function getStake(uint256 agentId) external view returns (uint256, uint256, uint256)',
]),
functionName: 'getStake',
args: [agentId],
});
console.log('Active stake:', amount);
console.log('Cooldown amount:', cooldownAmount);
// Begin unstaking (starts 5-minute cooldown)
const { request: unstakeReq } = await publicClient.simulateContract({
address: TRUST_VAULT,
abi: parseAbi(['function unstake(uint256 agentId, uint256 amount) external']),
functionName: 'unstake',
args: [agentId, parseEther('5000')], // Unstake 5,000 LABS
account: '0xYourAddress',
});
const unstakeHash = await walletClient.writeContract(unstakeReq);
// After cooldown expires, withdraw (receives native LABS)
const { request: withdrawReq } = await publicClient.simulateContract({
address: TRUST_VAULT,
abi: parseAbi(['function withdraw(uint256 agentId) external']),
functionName: 'withdraw',
args: [agentId],
account: '0xYourAddress',
});
const withdrawHash = await walletClient.writeContract(withdrawReq);ABI
[
"function stake(uint256 agentId, uint256 amount) external",
"function unstake(uint256 agentId, uint256 amount) external",
"function withdraw(uint256 agentId) external",
"function getTrustTier(uint256 agentId) external view returns (uint8 tier)",
"function getStake(uint256 agentId) external view returns (uint256 amount, uint256 cooldownAmount, uint256 cooldownEndTime)",
"event Staked(uint256 indexed agentId, uint256 amount, address indexed staker)",
"event Unstaked(uint256 indexed agentId, uint256 amount, uint256 cooldownEndTime)",
"event Withdrawn(uint256 indexed agentId, uint256 amount, address indexed recipient)"
]