Xphere · Union Validator Rewards

Stake XP. Burn the rest.

Every epoch, 100% of the foundation node's validator rewards flow in. The staker pool is sized against the full 35M cap: stakers receive 60% × filled capacity, and everything else — the base 40% plus every unfilled seat's share — is sent to the burn address, gone forever. No re-delegation, no lockup of principal beyond a 7-day cooldown.

Total Value Locked
of 35M cap
Effective APR
≈ constant: inflow × 60% × 365 ÷ 35M cap
Total Burned
permanently removed from supply
01

How each epoch settles

Validator inflow
≈27,027 XP / day
decays ×0.7273 every February — the system is agnostic to the amount
60% × staked ÷ 35M cap
Streamed to stakers
APR ≈ constant regardless of TVL · claim anytime
40%+
Burned forever
base 40% + every unfilled seat's share · 0x…dEaD
xphere-vault ~ settle.log

      

Anyone can call settle() once per epoch — it's permissionless. Principal and the reward pool are accounted separately, so even if the node is slashed or rewards stop, every staker can withdraw 100% of principal.

02

Stake & manage

How to call this from code
// ethers v6
const vault = new ethers.Contract(VAULT, ABI, signer);
// direct:
await vault.depositNative(receiver, { value: amount });
// via a partner referral (id = keccak256 of the partner slug):
const pid = ethers.id("ankr");
await vault.depositNativeWithReferral(receiver, pid, { value: amount });

Unstaking is a two-step, 7-day cooldown: requestRedeem burns your shares now, then claimRedeem returns principal after 7 days.

How to call this from code
// step 1 — request (shares = assets × 1000, fixed rate)
const shares = ethers.parseEther(amount) * 1000n;
const id = await vault.requestRedeem(shares, owner, owner);
// step 2 — after 7 days
await vault.claimRedeemNative(requestId, receiver);
Ready to claim
How to call this from code
// rewards accrue every second while staked
await vault.claimRewardNative(receiver); // native XP
// or keep it wrapped:
await vault.claimReward(receiver);       // WXP
03

Integrated platforms

External staking platforms route their users into this single vault with an on-chain partnerId. Attribution is fully transparent — anyone can verify each platform's routed TVL directly from the contract via partnerTVL(id).

PartnerRouted TVLShare

Platform integrations

Partnership terms and onboarding are arranged individually with the Foundation and are not published here. If your platform wants to offer XP staking to its users, reach out through the Foundation's business channel.

Contact the Foundation →
04

Call it from anywhere

Every contract is public and permissionless to read. Reads work with any RPC; writes need a signer. Addresses live in config.js.

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider(XPHERE_RPC);
const vault = new ethers.Contract(VAULT, [
  "function totalAssets() view returns (uint256)",
  "function currentAPR() view returns (uint256)",
  "function partnerTVL(bytes32) view returns (uint256)",
  "function earned(address) view returns (uint256)",
  "function depositNative(address) payable returns (uint256)",
  "function requestRedeem(uint256,address,address) returns (uint256)",
], provider);

// read effective APR (1e18 == 100%)
const apr = await vault.currentAPR();
console.log(Number(apr) / 1e16, "%");

// stake (with a signer)
const signer = await new ethers.BrowserProvider(window.ethereum).getSigner();
await vault.connect(signer).depositNative(await signer.getAddress(), {
  value: ethers.parseEther("100"),
});
import { createPublicClient, http, parseEther, formatUnits } from "viem";

const client = createPublicClient({ transport: http(XPHERE_RPC) });

const apr = await client.readContract({
  address: VAULT,
  abi: [{ name: "currentAPR", type: "function", stateMutability: "view",
          inputs: [], outputs: [{ type: "uint256" }] }],
  functionName: "currentAPR",
});
console.log(formatUnits(apr, 16), "%");

// total burned (from the distributor)
const burned = await client.readContract({
  address: DISTRIBUTOR,
  abi: [{ name: "totalBurned", type: "function", stateMutability: "view",
          inputs: [], outputs: [{ type: "uint256" }] }],
  functionName: "totalBurned",
});
# Foundry cast — read state
cast call $VAULT "totalAssets()(uint256)"        --rpc-url $XPHERE_RPC
cast call $VAULT "currentAPR()(uint256)"         --rpc-url $XPHERE_RPC
cast call $DISTRIBUTOR "totalBurned()(uint256)"  --rpc-url $XPHERE_RPC

# partner TVL (bytes32 id = keccak of the slug)
PID=$(cast keccak "ankr")
cast call $VAULT "partnerTVL(bytes32)(uint256)" $PID --rpc-url $XPHERE_RPC

# stake 100 XP (native), signed
cast send $VAULT "depositNative(address)(uint256)" $YOU \
  --value 100ether --rpc-url $XPHERE_RPC --private-key $PK

# settle the epoch (permissionless)
cast send $DISTRIBUTOR "settle()(uint256,uint256)" --rpc-url $XPHERE_RPC --private-key $PK