Savings GHO (sGHO) is a native ERC-4626 compliant vault for the GHO stablecoin, deployed on Ethereum mainnet. GHO deposited into the vault earns a fixed APR via an on-chain yield index — yield accrues continuously and is reflected in the GHO value of sGHO shares. There is no cooldown period, no slashing risk, and no rehypothecation of deposited funds.
Contract: 0xE1753F2e00940cC31213dd92013cF019DFE4ca1d (Ethereum Mainnet)
sGHO replaces the legacy Merit-based sGHO contract. Legacy holders must withdraw GHO from the old contract and deposit into the new vault to earn the current rate. See Legacy sGHO for the previous API.
Vault State
Fetch the current state of the sGHO vault, including rates, totals, and an optional user position.
- React
- TypeScript
- GraphQL
Use the useSghoVault hook to read vault data and an optional user position.
Vault State
import { useSghoVault, chainId, evmAddress } from "@aave/react";import { useAccount } from "wagmi";
// …
const { address } = useAccount();
const { data, loading, error } = useSghoVault({ chainId: chainId(1), user: address ? evmAddress(address) : undefined,});
if (loading) return <p>Loading…</p>;if (error) return <p>Error: {error.message}</p>;
// data.totalAssets — total GHO locked in the vault// data.targetRate — current fixed APR// data.supplyCap — maximum GHO that can be deposited// data.paused — whether deposits and withdrawals are blocked// data.user?.shares — user's sGHO shares balance// data.user?.balance — GHO value of the user's shares// data.user?.maxDeposit — max GHO the user can deposit// data.user?.maxWithdraw — max GHO the user can withdrawDeposit
Deposit GHO into the sGHO vault to start earning yield.
- React
- TypeScript
- GraphQL
Use the useSghoVaultDeposit hook to create the execution plan for depositing GHO.
Deposit GHO
import { useWalletClient } from "wagmi";import { useSghoVaultDeposit, bigDecimal, evmAddress, chainId } from "@aave/react";
// …
const { data: walletClient } = useWalletClient();
const [deposit, depositing] = useSghoVaultDeposit();
const execute = async () => { const result = await deposit({ amount: { value: bigDecimal(1000), // 1000 GHO }, depositor: evmAddress(walletClient!.account.address), chainId: chainId(1), // sharesRecipient: evmAddress("0x1234…"), // defaults to depositor });
// …};- React
- TypeScript
- GraphQL
Use the useSendTransaction hook for the wallet library of your choice to send the transactions in the execution plan.
Viem
import { useWalletClient } from "wagmi";import { errAsync, useSghoVaultDeposit } from "@aave/react";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();
const [deposit, depositing] = useSghoVaultDeposit();const [sendTransaction, sending] = useSendTransaction(walletClient);
const loading = depositing.loading || sending.loading;const error = depositing.error || sending.error;
// …
const execute = async () => { const result = await deposit({ // … }).andThen((plan) => { switch (plan.__typename) { case "TransactionRequest": return sendTransaction(plan);
case "ApprovalRequired": return sendTransaction(plan.approval).andThen(() => sendTransaction(plan.originalTransaction) );
case "InsufficientBalanceError": return errAsync( new Error(`Insufficient balance: ${plan.required.value} required.`) ); } });
if (result.isErr()) { console.error("Deposit failed:", result.error); } else { console.log("Deposit successful:", result.value); }};Redeem
Redeem sGHO shares for GHO. Withdrawals are atomic with no cooldown period.
- React
- TypeScript
- GraphQL
Use the useSghoVaultRedeemShares hook to create the execution plan. Pass maxRedeem: true to redeem all shares, or shares for an exact amount.
Redeem Shares
import { useWalletClient } from "wagmi";import { useSghoVaultRedeemShares, bigDecimal, evmAddress, chainId,} from "@aave/react";
// …
const { data: walletClient } = useWalletClient();
const [redeemShares, redeeming] = useSghoVaultRedeemShares();
const execute = async () => { const result = await redeemShares({ amount: { maxRedeem: true }, // or: { shares: bigDecimal(1000) } sharesOwner: evmAddress(walletClient!.account.address), chainId: chainId(1), // recipient: evmAddress("0x1234…"), // defaults to sharesOwner });
// …};- React
- TypeScript
- GraphQL
Use the useSendTransaction hook for the wallet library of your choice to send the transaction.
Viem
import { useWalletClient } from "wagmi";import { errAsync, useSghoVaultRedeemShares } from "@aave/react";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();
const [redeemShares, redeeming] = useSghoVaultRedeemShares();const [sendTransaction, sending] = useSendTransaction(walletClient);
const loading = redeeming.loading || sending.loading;const error = redeeming.error || sending.error;
// …
const execute = async () => { const result = await redeemShares({ // … }).andThen((plan) => { switch (plan.__typename) { case "TransactionRequest": return sendTransaction(plan);
case "InsufficientBalanceError": return errAsync( new Error( `Insufficient balance: ${plan.required.value} is the maximum redemption allowed.` ) ); } });
if (result.isErr()) { console.error("Redeem failed:", result.error); } else { console.log("Redeem successful:", result.value); }};Preview
Preview the outcome of a deposit or redeem before submitting a transaction. Useful for showing users expected shares or GHO amounts in a UI.
Preview Deposit
Returns the number of sGHO shares that would be minted for a given GHO deposit amount.
- React
- TypeScript
- GraphQL
Preview Deposit
import { useSghoVaultPreviewDeposit, chainId } from "@aave/react";
// …
const { data, loading, error } = useSghoVaultPreviewDeposit({ amount: "1000", // GHO to deposit chainId: chainId(1),});
if (loading) return <p>Loading…</p>;if (error) return <p>Error: {error.message}</p>;
// data: DecimalValue — sGHO shares to be mintedPreview Redeem
Returns the GHO amount that would be received for redeeming a given number of sGHO shares.
- React
- TypeScript
- GraphQL
Preview Redeem
import { useSghoVaultPreviewRedeem, chainId } from "@aave/react";
// …
const { data, loading, error } = useSghoVaultPreviewRedeem({ amount: "995", // sGHO shares to redeem chainId: chainId(1),});
if (loading) return <p>Loading…</p>;if (error) return <p>Error: {error.message}</p>;
// data: DecimalValue — GHO amount to be receivedLegacy sGHO
The Merit-based sGHO contract is being phased out. Users should withdraw GHO from the legacy contract and deposit into the new ERC-4626 sGHO vault to earn the current rate. The legacy reward rate steps down in phases until it reaches 0%.
The following API covers the legacy sGHO contract (Merit-based reward distribution via Merkl).
Deposit
To start earning rewards by depositing GHO into sGHO, follow these steps.
First, prepare the execution plan for the deposit operation.
- React
- TypeScript
- GraphQL
Use the useSavingsGhoDeposit hook to create the execution plan for depositing GHO to sGHO.
Deposit GHO
import { useWalletClient } from "wagmi";import { useSavingsGhoDeposit, bigDecimal, evmAddress } from "@aave/react";
// …
const { data: walletClient } = useWalletClient();
const [deposit, depositing] = useSavingsGhoDeposit();
const execute = async () => { const result = await deposit({ amount: { value: bigDecimal(1000), // 1000 GHO }, depositor: evmAddress(walletClient!.account.address), });
// …};Then, handle the execution plan.
- React
- TypeScript
- GraphQL
Use the useSendTransaction hook for the wallet library of your choice to send the transactions in the execution plan.
Viem
import { useWalletClient } from "wagmi";import { errAsync, useSavingsGhoDeposit } from "@aave/react";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();
const [deposit, depositing] = useSavingsGhoDeposit();const [sendTransaction, sending] = useSendTransaction(walletClient);
// …
const loading = depositing.loading || sending.loading;const error = depositing.error || sending.error;
// …
const execute = async () => { const result = await deposit({ // … }).andThen((plan) => { switch (plan.__typename) { case "TransactionRequest": // Single transaction execution return sendTransaction(plan);
case "ApprovalRequired": // Approval + transaction sequence return sendTransaction(plan.approval).andThen(() => sendTransaction(plan.originalTransaction) );
case "InsufficientBalanceError": return errAsync( new Error(`Insufficient balance: ${plan.required.value} required.`) ); } });
if (result.isErr()) { console.error("Deposit failed:", result.error); } else { console.log("Deposit successful with hash:", result.value); }};Balance
Retrieve the balance of a user's sGHO.
- React
- TypeScript
- GraphQL
Use the useSavingsGhoBalance hook to fetch the balance of a user's sGHO.
Fetch the balance of a user's sGHO.
sGHO Balance
import { useSavingsGhoBalance, evmAddress } from "@aave/react";
// …
const { data, loading, error } = useSavingsGhoBalance({ user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),});
if (loading) { return <p>Loading sGHO balance...</p>;}
if (error) { return <p>Error: {error.message}</p>;}
// data: TokenAmountWithdraw
Withdraw sGHO to GHO instantly with no cooldown period. You can still claim any previous rewards.
Follow these steps to withdraw sGHO to GHO:
First, prepare the execution plan for the withdrawal operation.
- React
- TypeScript
- GraphQL
Use the useSavingsGhoWithdraw hook to create the execution plan for withdrawing sGHO to GHO.
Withdraw GHO
import { useWalletClient } from "wagmi";import { useSavingsGhoWithdraw, bigDecimal, evmAddress } from "@aave/react";
// …
const { data: walletClient } = useWalletClient();
const [withdraw, withdrawing] = useSavingsGhoWithdraw();
const execute = async () => { const result = await withdraw({ amount: { value: bigDecimal(1000), // 1000 sGHO }, sharesOwner: evmAddress(walletClient!.account.address), // recipient: evmAddress("0x1234…"), if different from sharesOwner });
// …};Finally, handle the execution plan.
- React
- TypeScript
- GraphQL
Use the useSendTransaction hook for the wallet library of your choice to send the transaction.
Viem
import { useWalletClient } from "wagmi";import { useSavingsGhoWithdraw, bigDecimal, evmAddress, errAsync,} from "@aave/react";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();
const [withdraw, withdrawing] = useSavingsGhoWithdraw();const [sendTransaction, sending] = useSendTransaction(walletClient);
const loading = withdrawing.loading || sending.loading;const error = withdrawing.error || sending.error;
// …
const execute = async () => { const result = await withdraw({ amount: { value: bigDecimal(1000), // 1000 sGHO }, sharesOwner: evmAddress(walletClient!.account.address), // recipient: evmAddress("0x1234…"), if different from sharesOwner }).andThen((plan) => { switch (plan.__typename) { case "TransactionRequest": return sendTransaction(plan);
case "ApprovalRequired": return sendTransaction(plan.approval).andThen(() => sendTransaction(plan.originalTransaction) );
case "InsufficientBalanceError": return errAsync( new Error( `Insufficient balance to withdraw: ${plan.required.value} is the maximum withdrawal allowed.` ) ); } });
if (result.isErr()) { console.error("Withdraw failed:", result.error); } else { console.log("Withdraw successful:", result.value); }};Claiming Incentives
Users who deposit into the legacy sGHO become eligible for rewards distributed through Merkl.
These rewards are not automatically added to the sGHO balance, they must be claimed separately.
Users can claim rewards in two ways:
Through the ACI Merit UI for a simple interface to view and claim rewards
Using the SDK
Follow these steps to claim rewards using the SDK:
First, determine if a user has claimable rewards.
- React
- TypeScript
- GraphQL
Use the useUserMeritRewards hook to fetch the user's sGHO claimable rewards and the transaction to claim them.
Fetch the user's claimable rewards and the transaction to claim them.
sGHO Rewards
import { useUserMeritRewards, evmAddress, chainId } from "@aave/react";
// …
const sGHO_ADDRESS = evmAddress("0x1a88Df1cFe15Af22B3c4c783D4e6F7F9e0C1885d");
const { data, loading, error } = useUserMeritRewards({ user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"), chainId: chainId(1), filter: { tokens: [sGHO_ADDRESS], },});
if (loading) { return <p>Loading claimable rewards...</p>;}
if (error) { return <p>Error: {error.message}</p>;}
// data: UserMeritRewards | nullIf data is null, the user has no sGHO claimable rewards.
Finally, if the user has claimable rewards, they can claim them by sending the transaction.
- React
- TypeScript
- GraphQL
Use the useSendTransaction hook for the wallet library of your choice to send the transactions in the execution plan.
Viem
import { useWalletClient } from "wagmi";import { useUserMeritRewards } from "@aave/react";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();const { data } = useUserMeritRewards({ // … suspense: true,});
const [sendTransaction, sending] = useSendTransaction(walletClient);
// …
const execute = async () => { if (data !== null) { const result = await sendTransaction(data.transaction);
if (result.isErr()) { console.error(result.error.message); } else { console.log("sGHO claim rewards successful with hash:", result.value); } }};For more details, see the GHO Savings Upgrade forum post.