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.jsconstprovider=newethers.providers.JsonRpcProvider('http://kovan.infura.io/<API KEY>')constwallet=newethers.Wallet('0xdefiisawesome...', provider)// Create the main GEB objectconstgeb=newGeb('kovan', provider)// Get a SAFEconstsafe=awaitgeb.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 ${(awaitsafe.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.constglobalDebt=awaitgeb.contracts.safeEngine.globalDebt()constdebtCeiling=awaitgeb.contracts.safeEngine.globalDebtCeiling()constsystemCoinsToDraw=ethersUtils.parseEther('15')if(globalDebt.add(systemCoinsToDraw).gt(debtCeiling)) {thrownewError('Debt ceiling too low, not possible to draw this amount of system coins.')}// We're good to mint some system coins! constproxy=awaitgeb.getProxyAction(wallet.address)consttx=proxy.openLockETHAndGenerateDebt(ethersUtils.parseEther('1'),// Lock 1 Etherutils.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 Gweiconstpending=awaitwallet.sendTransaction(tx) // Send the transactionconsole.log(`Transaction ${pending.hash} waiting to be mined...`)awaitpending.wait() // Wait for it to be minedconsole.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),
])