This is a complete example of how you can inspect a SAFE and also open a new one using your own proxy:
import { ethers, utils as ethersUtils } from 'ethers'
import { Geb, utils } from 'geb.js'
// Setup Ether.js
const provider = new ethers.providers.JsonRpcProvider(
'http://kovan.infura.io/<API KEY>'
)
const wallet = new ethers.Wallet('0xdefiisawesome...', provider)
// Create the main GEB object
const geb = new Geb('kovan', provider)
// Get a SAFE
const safe = await geb.getSafe(4)
console.log(`Safe id 4 has: ${utils.wadToFixed(safe.debt).toString()} worth of debt.`)
console.log(`It will get liquidated if ETH price falls below ${(await safe.liquidationPrice())?.toString()} USD.`)
// Open a new SAFE, lock ETH and draw system coins in a single transaction using a proxy
// Note: Before doing this you need to create your own proxy
// We first need to check that the system didn't reach the debt ceiling so that we can
// mint more system coins.
const globalDebt = await geb.contracts.safeEngine.globalDebt()
const debtCeiling = await geb.contracts.safeEngine.globalDebtCeiling()
const systemCoinsToDraw = ethersUtils.parseEther('15')
if(globalDebt.add(systemCoinsToDraw).gt(debtCeiling)) {
throw new Error('Debt ceiling too low, not possible to draw this amount of system coins.')
}
// We're good to mint some system coins!
const proxy = await geb.getProxyAction(wallet.address)
const tx = proxy.openLockETHAndGenerateDebt(
ethersUtils.parseEther('1'), // Lock 1 Ether
utils.ETH_A, // Of collateral type ETH_A
systemCoinsToDraw // And draw 15 system coins
)
tx.gasPrice = ethers.BigNumber.from('80').mul('1000000000') // Set the gas price to 80 Gwei
const pending = await wallet.sendTransaction(tx) // Send the transaction
console.log(`Transaction ${pending.hash} waiting to be mined...`)
await pending.wait() // Wait for it to be mined
console.log('Transaction mined, safe opened!')
Additional examples
In the examples below we assume that variables are defined like in the complete example above.
const proxy = await geb.getProxyAction("0xdefidream...")
// You first need to approve your proxy to spend your system coins
let tx = geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)
// Repay 1 system coin worth of debt for SAFE #4
tx = proxy.repayDebt(4, ethersUtils.parseEther('1'))
await wallet.sendTransaction(tx)
Complete repayment of safe debt
const proxy = await geb.getProxyAction("0xdefidream...")
// You first need to approve your proxy to spend your system coins
let tx = geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)
// Repay all debt of SAFE #4
tx = proxy.repayAllDebt(4)
await wallet.sendTransaction(tx)
Withdraw Ether collateral
const proxy = await geb.getProxyAction("0xdefidream...")
// Unlock 1 ETH of collateral from SAFE #4 and transfer it to its owner
const tx = proxy.freeETH(4, ethersUtils.parseEther('1'))
await wallet.sendTransaction(tx)
Repay all debt and withdraw all collateral
const proxy = await geb.getProxyAction("0xdefidream...")
const safe = await geb.getSafe(4)
// You first need to approve your proxy to spend your system coins
let tx = geb.contracts.coin.approve(proxy.proxyAddress, ethers.constants.MaxUint256)
await wallet.sendTransaction(tx)
// Pay back everything and get your ETH back into your wallet
const tx = proxy.repayAllDebtAndFreeETH(4, safe.collateral)
await wallet.sendTransaction(tx)
Make direct contract calls
Geb.js exposes all contract APIs of all core contracts in the Geb.contracts object. Solidity functions that are read-only (view or pure) return asynchronously the expected value from the chain. State changing functions will return a transaction object to passed to ether.js or web3.
// Fetch some system parameters from their respective contracts
const surplusBuffer = await geb.contracts.accountingEngine.surplusBuffer()
const { stabilityFee } = await geb.contracts.taxCollector.collateralTypes(utils.ETH_A)
// Liquidate a Safe
const tx = geb.contracts.liquidationEngine.liquidateSAFE(utils.ETH_A,"0xdefidream...");
await wallet.sendTransaction(tx)
Multicall
Useful to bundle read-only calls in a single RPC call:
const [ globalDebt, collateralInfo ] = await geb.multiCall([
geb.contracts.safeEngine.globalDebt(true), // !! Note the last parameter set to true.
geb.contracts.safeEngine.collateralTypes(utils.ETH_A, true),
])