/install bifrost-slpx-stake
Bifrost SLPx Stake
Execute Bifrost vETH liquid staking operations: mint, redeem, and claim.
Contract & Network
vETH is deployed on Ethereum and three L2 networks. The same contract address is used across all chains.
| Chain | ChainId | VETH Contract | WETH (underlying) | Default RPC | Fallback RPC |
|---|---|---|---|---|---|
| Ethereum | 1 | 0xc3997ff81f2831929499c4eE4Ee4e0F08F42D4D8 |
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
https://ethereum.publicnode.com |
https://1rpc.io/eth |
| Base | 8453 | 0xc3997ff81f2831929499c4eE4Ee4e0F08F42D4D8 |
0x4200000000000000000000000000000000000006 |
https://base.publicnode.com |
https://1rpc.io/base |
| Optimism | 10 | 0xc3997ff81f2831929499c4eE4Ee4e0F08F42D4D8 |
0x4200000000000000000000000000000000000006 |
https://optimism.publicnode.com |
https://1rpc.io/op |
| Arbitrum | 42161 | 0xc3997ff81f2831929499c4eE4Ee4e0F08F42D4D8 |
0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 |
https://arbitrum-one.publicnode.com |
https://1rpc.io/arb |
Configuration
On first run, ask the user whether they want to configure custom settings. If not, use the defaults above.
Environment Variables
| Variable | Description | Default |
|---|---|---|
BIFROST_CHAIN |
Target chain name (ethereum, base, optimism, arbitrum) |
ethereum |
BIFROST_RPC_URL |
Custom RPC endpoint | Per-chain default from table above |
BIFROST_VETH_ADDRESS |
VETH contract address (override) | 0xc3997ff81f2831929499c4eE4Ee4e0F08F42D4D8 |
BIFROST_PRIVATE_KEY |
Private key for agent-side signing (hex, with or without 0x prefix) | Not set (manual signing mode) |
Wallet Setup
Two signing modes. Default is manual signing (no setup needed).
Default: Manual Signing
Output complete transaction details (to, value, data, gas, chainId). User signs with their own wallet (MetaMask, Ledger, CLI, etc.).
Option: Agent-Side Signing
Set BIFROST_PRIVATE_KEY as an environment variable, or import via Foundry keystore:
cast wallet import bifrost-agent --interactive
When BIFROST_PRIVATE_KEY is set, the agent can sign and broadcast transactions directly using cast send.
Quick Reference
Write Operations
| Operation | Function | Selector | Description |
|---|---|---|---|
| Mint vETH (via ETH) | depositWithETH() |
0x1166dab6 |
Stake native ETH to mint vETH. ETH is sent as msg.value. The contract wraps ETH → WETH internally — no ERC-20 approval needed. Reverts EthNotSent() if msg.value == 0 |
| Mint vETH (via WETH) | deposit(uint256,address) |
0x6e553f65 |
Deposit WETH directly to mint vETH for receiver. Requires prior WETH approval to the VETH contract |
| Redeem vETH | redeem(uint256,address,address) |
0xba087652 |
Burn shares of vETH to initiate ETH withdrawal for receiver. ETH enters a redemption queue and is NOT returned instantly. Requires owner == msg.sender or sufficient allowance |
| Claim as ETH | withdrawCompleteToETH() |
0x3ec549e9 |
Claim ALL completed withdrawals as native ETH. Internally calls withdrawCompleteTo(this) then unwraps WETH → ETH. Reverts EthTransferFailed() if ETH transfer fails |
| Claim as WETH | withdrawComplete() |
0x266a3bce |
Claim ALL completed withdrawals as WETH to msg.sender. Use this if withdrawCompleteToETH() fails |
| Claim to address | withdrawCompleteTo(address) |
0xf29ee493 |
Claim ALL completed withdrawals as WETH to a specified receiver address |
Pre-Execution Query Functions
| Query | Function | Selector | Description |
|---|---|---|---|
| Preview deposit | previewDeposit(uint256) |
0xef8b30f7 |
Simulate deposit and return exact vETH shares to be minted |
| Preview redeem | previewRedeem(uint256) |
0x4cdad506 |
Simulate redemption and return exact ETH to be returned |
| Fallback: shares calc | convertToShares(uint256) |
0xc6e6f592 |
Convert ETH amount to vETH shares using current Oracle exchange rate |
| Fallback: assets calc | convertToAssets(uint256) |
0x07a2d13a |
Convert vETH shares to ETH value using current Oracle exchange rate |
| vETH balance | balanceOf(address) |
0x70a08231 |
Get vETH token balance of a specific address |
| Max redeemable | maxRedeem(address) |
0xd905777e |
Maximum vETH shares the owner can redeem in a single tx |
| Claimable ETH | canWithdrawalAmount(address) |
0x52a630b9 |
Returns (totalAvailableAmount, pendingDeleteIndex, pendingDeleteAmount). First value = ETH ready to claim |
How to Call
Read queries — use eth_call (no gas):
# Method A: cast (preferred)
cast call \x3CVETH_CONTRACT> \
"\x3CFUNCTION_SIGNATURE>(\x3CARG_TYPES>)(\x3CRETURN_TYPES>)" \x3CARGS> \
--rpc-url \x3CRPC_URL>
# Method B: curl (if cast unavailable)
curl -s -X POST \x3CRPC_URL> \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"\x3CVETH_CONTRACT>","data":"\x3CSELECTOR>\x3CENCODED_ARGS>"},"latest"]}'
If previewDeposit or previewRedeem fails, fall back to convertToShares / convertToAssets (same encoding).
Write transactions — use cast send (requires wallet):
# Mint vETH (stake native ETH)
cast send \x3CVETH_CONTRACT> \
"depositWithETH()" --value \x3CAMOUNT_IN_WEI> \
--rpc-url \x3CRPC_URL> --private-key \x3CPRIVATE_KEY>
# Redeem vETH (unstake)
cast send \x3CVETH_CONTRACT> \
"redeem(uint256,address,address)" \x3CSHARES_IN_WEI> \x3CUSER_ADDR> \x3CUSER_ADDR> \
--rpc-url \x3CRPC_URL> --private-key \x3CPRIVATE_KEY>
# Claim ETH (withdraw completed redemptions)
cast send \x3CVETH_CONTRACT> \
"withdrawCompleteToETH()" \
--rpc-url \x3CRPC_URL> --private-key \x3CPRIVATE_KEY>
Calldata Encoding (for manual signing output)
- uint256: convert wei to hex, left-pad to 64 chars
- address: remove 0x prefix, left-pad to 64 chars
canWithdrawalAmountreturns 3 × uint256 (192 hex chars):(totalAvailableAmount, pendingDeleteIndex, pendingDeleteAmount). First 64 chars = claimable ETH amount
API 1: Mint vETH (Stake ETH)
Pre-Execution
- Query rate:
previewDeposit(amount)→ expected vETH - Check wallet:
BIFROST_PRIVATE_KEYenv var or Foundry keystorebifrost-agent - Display preview and wait for CONFIRM
Transaction
| Field | Value |
|---|---|
| To | \x3CVETH_CONTRACT> |
| Value | User's ETH amount in wei |
| Data | 0x1166dab6 |
| ChainId | Per selected chain |
Manual Signing Output
To: \x3CVETH_CONTRACT>
Value: {wei} ({amount} ETH)
Data: 0x1166dab6
ChainId: {chainId}
API 2: Redeem vETH (Unstake)
Pre-Execution
- Check
balanceOf(user)≥ redeem amount - Query
previewRedeem(shares)→ expected ETH - Check
maxRedeem(user) - Display preview (warn: ETH enters queue, NOT instant) and wait for CONFIRM
Transaction
| Field | Value |
|---|---|
| To | \x3CVETH_CONTRACT> |
| Value | 0 |
| Data | ABI-encoded redeem(shares, userAddr, userAddr) |
| ChainId | Per selected chain |
Encode calldata: cast calldata "redeem(uint256,address,address)" \x3CSHARES> \x3CADDR> \x3CADDR>
API 3: Claim Redeemed ETH
Pre-Execution
- Check
canWithdrawalAmount(user)— first return value = claimable amount - If 0: inform user redemption may still be processing
- If > 0: display claimable amount and wait for CONFIRM
Transaction
| Field | Value |
|---|---|
| To | \x3CVETH_CONTRACT> |
| Value | 0 |
| Data | 0x3ec549e9 |
| ChainId | Per selected chain |
Agent Behavior
- Environment check: on first interaction, ask user if they want to configure
BIFROST_CHAIN,BIFROST_RPC_URL, orBIFROST_PRIVATE_KEY. If not, use Ethereum Mainnet defaults with manual signing mode - RPC selection: use
BIFROST_RPC_URLif set; otherwise use per-chain default RPC. Fall back to per-chain fallback RPC on failure - Multi-chain awareness: when user specifies a chain (e.g. "on Base", "on Arbitrum"), switch to that chain's RPC, WETH address, and chainId accordingly
- Wallet detection: check
BIFROST_PRIVATE_KEYenv var or Foundry keystorebifrost-agent. If found, ask user whether to use it. If not, output tx data for manual signing - CONFIRM required: display transaction preview (amount, rate, expected output, chain) and require user to type CONFIRM before any write
- Private key import requires CONFIRM: show security warning first, require CONFIRM before accepting key
- Key retention is user-controlled: after tx, ask user whether to keep or delete the key
- Balance pre-check: verify sufficient ETH/vETH before building tx
- Prefer cast, fall back to curl: use pre-computed calldata from selector table if cast fails
- No credential display: never echo private keys; truncate addresses (first 6 + last 4)
- Post-completion tip: if no wallet configured, suggest "set up wallet" after operation
- After successful tx, provide block explorer link:
https://etherscan.io/tx/{hash}(Ethereum),https://basescan.org/tx/{hash}(Base),https://optimistic.etherscan.io/tx/{hash}(Optimism),https://arbiscan.io/tx/{hash}(Arbitrum) - Useful links: direct users to Bifrost vETH page or Bifrost App when relevant
Security
- Private keys are opt-in only — default outputs unsigned tx data
- Explicit CONFIRM for every write operation
- Validate amounts against balance and protocol limits
- Recommend dedicated wallet with limited funds for agent-side signing
Error Handling
| Error | User Message |
|---|---|
EthNotSent() (0x8689d991) |
"No ETH included. Please specify the amount." |
EthTransferFailed() |
"ETH transfer failed. Try claiming as WETH with withdrawComplete()." |
ZeroWithdrawAmount() (0xd6d9e665) |
"No claimable ETH. Your redemption may still be processing." |
ERC4626ExceededMaxRedeem (0xb94abeec) |
"Redeem exceeds your maximum. Check balance." |
Pausable: paused |
"VETH contract is paused. Try again later." |
| Insufficient ETH | "Insufficient ETH. Balance: {bal}, Needed: {amount + gas}." |
| Insufficient vETH | "Insufficient vETH. Balance: {bal}, Requested: {amount}." |
| Max withdraw count exceeded | "Too many pending redemptions. Claim existing ones first." |
| RPC failure | "Unable to connect. Retrying with backup endpoint..." |
Notes
depositWithETH()wraps ETH → WETH internally viaWETH.deposit(). No ERC-20 approval needed. For direct WETH deposits, usedeposit(uint256,address)instead (requires WETH approval)withdrawCompleteToETH()internally callswithdrawCompleteTo(address(this))to receive WETH, then unwraps to ETH viaWETH.withdraw(), then sends ETH to caller. If ETH transfer fails, usewithdrawComplete()to receive WETH instead- Redemption is NOT instant —
redeem()/withdraw()add entries to the withdrawal queue, processed in batches via Bifrost cross-chain mechanism - All write functions are protected by
whenNotPausedandnonReentrant(ReentrancyGuardUpgradeable) - Gas estimates are approximate; use
cast estimatefor accuracy
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install bifrost-slpx-stake - 安装完成后,直接呼叫该 Skill 的名称或使用
/bifrost-slpx-stake触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Bifrost Slpx Stake 是什么?
Execute liquid staking operations on Bifrost SLPx protocol across Ethereum, Base, Optimism, and Arbitrum. Mint vETH by staking ETH/WETH, redeem vETH back to... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 251 次。
如何安装 Bifrost Slpx Stake?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install bifrost-slpx-stake」即可一键安装,无需额外配置。
Bifrost Slpx Stake 是免费的吗?
是的,Bifrost Slpx Stake 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Bifrost Slpx Stake 支持哪些平台?
Bifrost Slpx Stake 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Bifrost Slpx Stake?
由 Edwin(@ark930)开发并维护,当前版本 v0.1.0。