Install
openclaw skills install stakingverse-luksoClawHub Security found sensitive or high-impact capabilities. Review the scan results before using.
Stake LYX tokens on Stakingverse (LUKSO liquid staking). Use when the user wants to stake LYX, unstake LYX, claim rewards, or check sLYX balance on Stakingverse. Supports deposit, withdrawal requests, and oracle-claim pattern.
openclaw skills install stakingverse-luksoStake LYX on Stakingverse and receive sLYX (liquid staking token). Earn ~8% APY while keeping your assets liquid.
Set these environment variables or edit the scripts:
export STAKINGVERSE_VAULT="0x9F49a95b0c3c9e2A6c77a16C177928294c0F6F04"
export MY_UP="your_universal_profile_address"
export CONTROLLER="your_controller_address"
export PRIVATE_KEY="your_controller_private_key"
export RPC_URL="https://rpc.mainnet.lukso.network"
# Stake 10 LYX
node scripts/stake.js 10
# Check sLYX balance
node scripts/balance.js
# Request unstake of 5 sLYX
node scripts/unstake-request.js 5
# Check if withdrawal is ready
node scripts/check-claim.js
# Claim unstaked LYX (after oracle processes)
node scripts/claim.js
Stakingverse is a liquid staking protocol on LUKSO:
| Contract | Address | Purpose |
|---|---|---|
| Vault | 0x9F49a95b0c3c9e2A6c77a16C177928294c0F6F04 | Staking/unstaking logic |
| sLYX Token | 0x8a3982f4abcdc30f777910e8b5b5d8242628290a | Liquid staking token (LSP7) |
| Oracle | Multiple | Validates withdrawal requests |
You (Controller)
↓
KeyManager.execute()
↓
UP.execute(CALL, Vault, 10 LYX, deposit())
↓
Vault receives LYX
↓
Vault mints sLYX to your UP
↓
You hold sLYX (earning rewards)
Step 1: Request Withdrawal
You (Controller)
↓
KeyManager.execute()
↓
UP.execute(CALL, Vault, 0, withdraw(sLYX_amount))
↓
Vault burns sLYX
↓
Oracle queue: withdrawal request created
Step 2: Wait for Oracle
↓ (Time passes - oracle processes)
Step 3: Claim LYX
You (Controller)
↓
KeyManager.execute()
↓
UP.execute(CALL, Vault, 0, claim())
↓
Oracle approves
↓
Vault sends LYX to your UP
const { ethers } = require('ethers');
// Setup
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
// Vault ABI (minimal)
const VAULT_ABI = [
'function deposit() external payable',
'function balanceOf(address) view returns (uint256)'
];
const LSP0_ABI = [
'function execute(uint256 operation, address target, uint256 value, bytes calldata data) external'
];
const LSP6_ABI = [
'function execute(bytes calldata payload) external payable returns (bytes memory)'
];
// Amount to stake
const stakeAmount = ethers.parseEther('10'); // 10 LYX
// Encode deposit call on Vault
const vaultInterface = new ethers.Interface(VAULT_ABI);
const depositData = vaultInterface.encodeFunctionData('deposit');
// Encode execute call on UP
const upInterface = new ethers.Interface(LSP0_ABI);
const executeData = upInterface.encodeFunctionData('execute', [
0, // operation: CALL
process.env.STAKINGVERSE_VAULT, // target: Vault
stakeAmount, // value: LYX to stake
depositData // data: deposit()
]);
// Send via KeyManager
const keyManager = new ethers.Contract(process.env.KEY_MANAGER, LSP6_ABI, wallet);
const tx = await keyManager.execute(executeData);
const receipt = await tx.wait();
console.log(`Staked ${ethers.formatEther(stakeAmount)} LYX`);
console.log(`Transaction: ${receipt.hash}`);
const SLYX_ABI = ['function balanceOf(address) view returns (uint256)'];
const slyx = new ethers.Contract(
'0x8a3982f4abcdc30f777910e8b5b5d8242628290a',
SLYX_ABI,
provider
);
const balance = await slyx.balanceOf(process.env.MY_UP);
console.log(`sLYX Balance: ${ethers.formatEther(balance)}`);
const amountToUnstake = ethers.parseEther('5'); // 5 sLYX
// Encode withdraw call on Vault
const withdrawData = vaultInterface.encodeFunctionData('withdraw', [amountToUnstake]);
// Encode execute call on UP
const executeData = upInterface.encodeFunctionData('execute', [
0, // operation: CALL
process.env.STAKINGVERSE_VAULT, // target: Vault
0, // value: 0 (no ETH sent)
withdrawData // data: withdraw(amount)
]);
// Send via KeyManager
const tx = await keyManager.execute(executeData);
await tx.wait();
console.log(`Unstake requested for ${ethers.formatEther(amountToUnstake)} sLYX`);
console.log('Wait for oracle processing, then run claim.js');
const VAULT_FULL_ABI = [
'function getClaimableAmount(address) view returns (uint256)',
'function getPendingWithdrawals(address) view returns (uint256)'
];
const vault = new ethers.Contract(
process.env.STAKINGVERSE_VAULT,
VAULT_FULL_ABI,
provider
);
const claimable = await vault.getClaimableAmount(process.env.MY_UP);
const pending = await vault.getPendingWithdrawals(process.env.MY_UP);
console.log(`Claimable LYX: ${ethers.formatEther(claimable)}`);
console.log(`Pending withdrawals: ${ethers.formatEther(pending)}`);
// Encode claim call on Vault (no parameters)
const claimData = vaultInterface.encodeFunctionData('claim');
// Encode execute call on UP
const executeData = upInterface.encodeFunctionData('execute', [
0,
process.env.STAKINGVERSE_VAULT,
0,
claimData
]);
// Send via KeyManager
const tx = await keyManager.execute(executeData);
const receipt = await tx.wait();
console.log(`Claimed LYX to your UP`);
console.log(`Transaction: ${receipt.hash}`);
All transactions must follow this flow:
// 1. Encode the target contract call
const targetData = targetInterface.encodeFunctionData('functionName', [args]);
// 2. Encode UP.execute() wrapper
const upData = upInterface.encodeFunctionData('execute', [
0, // operation type (0 = CALL)
targetAddress, // target contract
value, // LYX to send (0 for most calls)
targetData // encoded function call
]);
// 3. Send via KeyManager
const tx = await keyManager.execute(upData);
CALL and TRANSFERVALUE permissionskeyManager.getPermissions(controllerAddress)sLYX.balanceOf(UP_ADDRESS)0x8a3982f4abcdc30f777910e8b5b5d8242628290a