Ethena allows apps to earn yield by staking USDe into the sUSDe vault. The sUSDe vault follows the ERC-4626 standard — your app deposits USDe and receives sUSDe shares that automatically accrue yield over time. There is no minimum staking period, and rewards are distributed every 8 hours.
Resources
Getting USDe
Your app can swap any supported token for USDe on any major decentralized exchange using a DEX aggregator or router.
Stake USDe into the sUSDe vault
1. Configure addresses
Set up the sUSDe vault and USDe token addresses. The example below uses Ethereum Mainnet:const SUSDE_VAULT_ADDRESS = '0x9D39A5DE30e57443BfF2A8307A4256c8797A3497';
const USDE_ADDRESS = '0x4c9EDD5852cd905f086C759E8383e09bff1E68B3';
const CHAIN_ID = 1; // Ethereum Mainnet
2. Approve the sUSDe vault to spend USDe
Use viem’s encodeFunctionData to encode the approval, and Privy’s useSendTransaction to send it:import {encodeFunctionData, maxUint256, erc20Abi} from 'viem';
import {useSendTransaction} from '@privy-io/react-auth';
const {sendTransaction} = useSendTransaction();
const data = encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: [SUSDE_VAULT_ADDRESS as `0x${string}`, maxUint256]
});
const tx = await sendTransaction({
to: USDE_ADDRESS as `0x${string}`,
data,
chainId: CHAIN_ID
});
3. Deposit USDe into the vault
Use viem to encode the deposit and Privy’s useSendTransaction to stake USDe:import {encodeFunctionData, parseUnits} from 'viem';
import {useSendTransaction} from '@privy-io/react-auth';
const {sendTransaction} = useSendTransaction();
const erc4626Abi = [
{
type: 'function',
name: 'deposit',
inputs: [
{name: 'assets', type: 'uint256'},
{name: 'receiver', type: 'address'}
],
outputs: [{name: 'shares', type: 'uint256'}],
stateMutability: 'nonpayable'
}
] as const;
const depositAmount = parseUnits('100', 18); // 100 USDe (18 decimals)
const data = encodeFunctionData({
abi: erc4626Abi,
functionName: 'deposit',
args: [depositAmount, address]
});
const tx = await sendTransaction({
to: SUSDE_VAULT_ADDRESS as `0x${string}`,
data,
chainId: CHAIN_ID
});
Check balance
Call the vault’s balanceOf function to get the user’s sUSDe shares, then call convertToAssets to see the current USDe value including accrued yield.
import {publicClient} from './viem';
const erc4626Abi = [
{
type: 'function',
name: 'balanceOf',
inputs: [{name: 'account', type: 'address'}],
outputs: [{name: '', type: 'uint256'}],
stateMutability: 'view'
},
{
type: 'function',
name: 'convertToAssets',
inputs: [{name: 'shares', type: 'uint256'}],
outputs: [{name: '', type: 'uint256'}],
stateMutability: 'view'
}
] as const;
const userShares = await publicClient.readContract({
address: SUSDE_VAULT_ADDRESS as `0x${string}`,
abi: erc4626Abi,
functionName: 'balanceOf',
args: [address]
});
const usdeValue = await publicClient.readContract({
address: SUSDE_VAULT_ADDRESS as `0x${string}`,
abi: erc4626Abi,
functionName: 'convertToAssets',
args: [userShares]
});
Unstake from the vault
Ethena has a 7-day cooldown period for unstaking. Your app must first request an unstake, which places the USDe in the USDeSilo contract. After the cooldown completes, your app can withdraw the USDe.
Unlike instant withdrawal vaults, Ethena requires a 7-day cooldown period after requesting an
unstake before USDe can be withdrawn.
Call cooldownShares on the sUSDe vault to initiate the unstaking process. The USDe is placed in the USDeSilo contract during the cooldown period.import {encodeFunctionData} from 'viem';
import {useSendTransaction} from '@privy-io/react-auth';
const {sendTransaction} = useSendTransaction();
const cooldownAbi = [
{
type: 'function',
name: 'cooldownShares',
inputs: [{name: 'shares', type: 'uint256'}],
outputs: [{name: 'assets', type: 'uint256'}],
stateMutability: 'nonpayable'
}
] as const;
const data = encodeFunctionData({
abi: cooldownAbi,
functionName: 'cooldownShares',
args: [userShares]
});
const tx = await sendTransaction({
to: SUSDE_VAULT_ADDRESS as `0x${string}`,
data,
chainId: CHAIN_ID
});
After the 7-day cooldown period has passed, call unstake on the sUSDe vault to withdraw USDe from the USDeSilo contract:import {encodeFunctionData} from 'viem';
import {useSendTransaction} from '@privy-io/react-auth';
const {sendTransaction} = useSendTransaction();
const unstakeAbi = [
{
type: 'function',
name: 'unstake',
inputs: [{name: 'receiver', type: 'address'}],
outputs: [],
stateMutability: 'nonpayable'
}
] as const;
const data = encodeFunctionData({
abi: unstakeAbi,
functionName: 'unstake',
args: [address]
});
const tx = await sendTransaction({
to: SUSDE_VAULT_ADDRESS as `0x${string}`,
data,
chainId: CHAIN_ID
});
Key integration tips
- Always approve first: Your app must grant ERC-20 approval to the sUSDe vault before any deposit.
- USDe uses 18 decimals: Use
parseUnits('100', 18) for amounts.
- Use
convertToAssets for real-time balances: This ERC-4626 method converts sUSDe shares to their current USDe value, including accrued yield.
- Plan for the 7-day cooldown: Unlike other yield protocols, Ethena requires a cooldown period before withdrawing staked USDe. During this period, the USDe is held in the USDeSilo contract.
- No minimum staking period: Your app can stake and unstake in consecutive blocks, though the 7-day cooldown still applies for withdrawals.
- sUSDe value only increases: Rewards can only be positive or zero — stakers cannot lose USDe by staking.
- Supported chains: Ethena sUSDe staking is available on Ethereum Mainnet.
Conclusion
Privy makes it straightforward to build secure, user-friendly access to Ethena yield. For advanced use cases, refer to the Ethena Staking Docs, or reach out in Slack.
Your app is now ready to interact with Ethena using Privy embedded wallets!