Savings GHO (sGHO)
Savings GHO (sGHO) is the Aave Protocol's native savings mechanism for the GHO stablecoin, deployed on Ethereum mainnet. sGHO allows GHO holders to supply their tokens to a smart contract and receive sGHO that accumulates rewards paid in GHO. This mechanism has no cooldowns to redeem sGHO for GHO, no slashing risk, and no rehypothecation of supplied funds. All rewards for sGHO holders are distributed through the Merit program.
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,});
if (loading) { return <p>Loading sGHO balance...</p>;}
if (error) { return <p>Error: {error.message}</p>;}
// data: TokenAmount
Withdraw
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": // 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 to withdraw: ${plan.required.value} is the maximum withdrawal allowed.` ) ); } });
if (loading) { return <p>Withdrawing sGHO to GHO...</p>; }
if (error) { return <p>Error: {error.message}</p>; }};
Claiming Incentives
Users who deposit into 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 | null
If 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.