This is a minimal example of a financial template that depends on price requests from the Optimistic Oracle. This contract should be thought of as a "Deposit Box" into which the user deposits some ERC20 collateral. The main feature of this box is that the user can withdraw their ERC20 corresponding to a desired USD amount. When the user wants to make a withdrawal, a price request is made to the Optimistic Oracle. For simplicity, the user is constrained to have one outstanding withdrawal request at any given time. Final fees are charged to the proposer of a price but not to the contract making a price request.
This example is intended to accompany a technical tutorial for how to integrate the Optimistic Oracle into a project. The main feature this demo serves to showcase is how to build a financial product on-chain that "pulls" price requests from the Optimistic Oracle on-demand, which is an implementation of the "priceless" oracle framework.
The typical user flow would be:
- User sets up a deposit box for the ETH/USD price-identifier. The "collateral currency" in this deposit box is therefore wETH. The user can subsequently make withdrawal requests for USD-denominated amounts of wETH.
- User deposits 10 wETH into their deposit box.
- User later requests to withdraw $10,000 USD of wETH.
- OptimisticDepositBox asks Optimistic Oracle for latest ETH/USD exchange rate.
- Optimistic Oracle resolves the exchange rate at: 1 wETH is worth 2000 USD.
- OptimisticDepositBox transfers 5 wETH to user.
constructor(address _collateralAddress, address _finderAddress, bytes32 _priceIdentifier, address _timerAddress) (public)
Construct the OptimisticDepositBox.
- _collateralAddress: ERC20 token to be deposited.
- _finderAddress: UMA protocol Finder used to discover other protocol contracts.
- _priceIdentifier: registered in the DVM, used to price the ERC20 deposited. The price identifier consists of a "base" asset and a "quote" asset. The "base" asset corresponds to the collateral ERC20 currency deposited into this account, and it is denominated in the "quote" asset on withdrawals. An example price identifier would be "ETH/USD" which will resolve and return the USD price of ETH.
- _timerAddress: contract that stores the current time in a testing environment. Must be set to 0x0 for production environments that use live time.
deposit(uint256 collateralAmount) (public)
collateralCurrency into caller's deposit box.
This contract must be approved to spend at least
- collateralAmount: total amount of collateral tokens to be sent to the sponsor's position.
requestWithdrawal(uint256 denominatedCollateralAmount) (public)
Starts a withdrawal request that allows the sponsor to withdraw
from their position denominated in the quote asset of the price identifier, following a Optimistic
Oracle price resolution.
The request will be pending for the duration of the liveness period and can be cancelled at any time. Only one withdrawal request can exist for the user.
- denominatedCollateralAmount: the quote-asset denominated amount of collateral requested to withdraw.
executeWithdrawal() → uint256 amountWithdrawn (external)
After a withdrawal request (i.e., by a call to
requestWithdrawal) and optimistic oracle
price resolution, withdraws
depositBoxData.withdrawalRequestAmount of collateral currency
denominated in the quote asset.
Might not withdraw the full requested amount in order to account for precision loss.
Cancels a pending withdrawal request.
getCollateral(address user) → uint256 (external)
Accessor method for a user's collateral.
- user: address whose collateral amount is retrieved.
_requestOraclePrice(uint256 requestedTime) (internal)
_resetWithdrawalRequest(struct OptimisticDepositBox.OptimisticDepositBoxData depositBoxData) (internal)
_depositBoxHasNoPendingWithdrawal(address user) (internal)
_getOptimisticOracle() → contract OptimisticOracleInterface (internal)
_getIdentifierWhitelist() → contract IdentifierWhitelistInterface (internal)
_getAddressWhitelist() → contract AddressWhitelist (internal)
_getOraclePrice(uint256 withdrawalRequestTimestamp) → uint256 (internal)
setCurrentTime(uint256 time) (external)
Sets the current time.
Will revert if not running in test mode.
- time: timestamp to set current Testable time to.
getCurrentTime() → uint256 (public)
Gets the current time. Will return the last time set in
setCurrentTime if running in test mode.
Otherwise, it will return the block timestamp.
Deposit(address user, uint256 collateralAmount)
RequestWithdrawal(address user, uint256 collateralAmount, uint256 withdrawalRequestTimestamp)
RequestWithdrawalExecuted(address user, uint256 collateralAmount, uint256 exchangeRate, uint256 withdrawalRequestTimestamp)
RequestWithdrawalCanceled(address user, uint256 collateralAmount, uint256 withdrawalRequestTimestamp)
Prevents a contract from calling itself, directly or indirectly.
nonReentrant function from another
nonReentrant function is not supported. It is possible to
prevent this from happening by making the
nonReentrant function external, and making it call a
function that does the actual state modification.
Designed to prevent a view-only method from being re-entered during a call to a
nonReentrant() state-changing method.
Reverts if not running in test mode.