Skip to main content

osToken ERC-20 operations

osETH and osGNO are standard ERC-20 tokens with EIP-2612 permit support. The StakeWise V3 SDK exposes the osToken contract for the configured network as sdk.contracts.tokens.mintToken, which automatically resolves to the correct address (osETH on Mainnet/Hoodi, osGNO on Gnosis Chain).

OsToken contract addresses (also available in Networks):

  • osETH on Ethereum Mainnet: 0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38
  • osETH on Hoodi testnet: 0x7345fC8268459413beE9e9dd327f31283C65Ee7e
  • osGNO on Gnosis Chain: 0xF490c80aAE5f2616d3e3BDa2483E30C4CB21d1A0

Transfer osGNO to another address (Gnosis Chain)

import { BrowserProvider, parseEther } from 'ethers'
import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'

const eip1193Provider = window.ethereum

const browserProvider = new BrowserProvider(eip1193Provider, {
chainId: Network.Gnosis,
name: 'gnosis',
})

const sdk = new StakeWiseSDK({
network: Network.Gnosis,
provider: browserProvider,
})

type Input = {
amount: string
userAddress: string
toAddress: string
}

const transferOsGno = async (values: Input) => {
const { amount, userAddress, toAddress } = values

try {
const value = parseEther(amount)
const osTokenContract = sdk.contracts.tokens.mintToken

const balance = await osTokenContract.balanceOf(userAddress)

if (balance < value) {
throw new Error('Insufficient osGNO balance.')
}

const signer = await sdk.provider.getSigner(userAddress)
const signedContract = osTokenContract.connect(signer)

const tx = await signedContract.transfer(toAddress, value)

await sdk.provider.waitForTransaction(tx.hash)
}
catch (error) {
console.error(error)
}
}

transferOsGno({
amount: '0.5', // osGNO
userAddress: 'USER_ADDRESS',
toAddress: 'RECIPIENT_ADDRESS',
})

Transfer osETH to another address (Ethereum Mainnet)

The same code works on Ethereum — only the network in the SDK constructor changes. sdk.contracts.tokens.mintToken automatically resolves to the osETH contract.

import { BrowserProvider, parseEther } from 'ethers'
import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'

const eip1193Provider = window.ethereum

const browserProvider = new BrowserProvider(eip1193Provider, {
chainId: Network.Mainnet,
name: 'mainnet',
})

const sdk = new StakeWiseSDK({
network: Network.Mainnet,
provider: browserProvider,
})

type Input = {
amount: string
userAddress: string
toAddress: string
}

const transferOsEth = async (values: Input) => {
const { amount, userAddress, toAddress } = values

try {
const value = parseEther(amount)
const osTokenContract = sdk.contracts.tokens.mintToken

const balance = await osTokenContract.balanceOf(userAddress)

if (balance < value) {
throw new Error('Insufficient osETH balance.')
}

const signer = await sdk.provider.getSigner(userAddress)
const signedContract = osTokenContract.connect(signer)

const tx = await signedContract.transfer(toAddress, value)

await sdk.provider.waitForTransaction(tx.hash)
}
catch (error) {
console.error(error)
}
}

transferOsEth({
amount: '0.5', // osETH
userAddress: 'USER_ADDRESS',
toAddress: 'RECIPIENT_ADDRESS',
})

Approve a spender (e.g. a DeFi protocol)

import { BrowserProvider, parseEther } from 'ethers'
import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'

const eip1193Provider = window.ethereum

const browserProvider = new BrowserProvider(eip1193Provider, {
chainId: Network.Mainnet,
name: 'mainnet',
})

const sdk = new StakeWiseSDK({
network: Network.Mainnet,
provider: browserProvider,
})

type Input = {
amount: string
userAddress: string
spenderAddress: string
}

const approveOsToken = async (values: Input) => {
const { amount, userAddress, spenderAddress } = values

try {
const value = parseEther(amount)
const osTokenContract = sdk.contracts.tokens.mintToken

const signer = await sdk.provider.getSigner(userAddress)
const signedContract = osTokenContract.connect(signer)

const tx = await signedContract.approve(spenderAddress, value)

await sdk.provider.waitForTransaction(tx.hash)
}
catch (error) {
console.error(error)
}
}

approveOsToken({
amount: '1.0', // osETH
userAddress: 'USER_ADDRESS',
spenderAddress: 'SPENDER_CONTRACT_ADDRESS',
})

Read balance and allowance

import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'
import { formatEther } from 'ethers'

const sdk = new StakeWiseSDK({
network: Network.Mainnet,
endpoints: {
web3: 'https://mainnet.infura.io/v3/...',
},
})

type Input = {
ownerAddress: string
spenderAddress: string
}

const readOsTokenState = async (values: Input) => {
const { ownerAddress, spenderAddress } = values

try {
const osTokenContract = sdk.contracts.tokens.mintToken

const [ balance, allowance ] = await Promise.all([
osTokenContract.balanceOf(ownerAddress),
osTokenContract.allowance(ownerAddress, spenderAddress),
])

console.log('osETH balance:', formatEther(balance))
console.log('osETH allowance:', formatEther(allowance))
}
catch (error) {
console.error(error)
}
}

readOsTokenState({
ownerAddress: 'USER_ADDRESS',
spenderAddress: 'SPENDER_CONTRACT_ADDRESS',
})