Skip to content

Depot

Work in Progress

This needs to be properly cleaned up.

Description

Old: Depot.sol: Allows users to exchange BNB for oUSD and OKS (has not yet been updated for multicurrency).

Throughout, the contract assumes that oUSD is always worth exactly US$1. So: a) this will only work with oUSD. b) there's a profit opportunity if the oUSD is off its peg.

Note

Some of this code is lifted verbatim from the old EtherNomin code, but this isn't indicated in the licence header.

Zero Transfer Fee

SIP-19 deprecated transfer fees. Hence, although exchange operations call FeePool.amountReceivedFromTransfer to subtract this fee from the sale quantity, the fee function just returns its argument unchanged, so nothing is actually charged.

Source: Depot.sol

Architecture


Inheritance Graph

Depot inheritance graph



Libraries


Structs


synthDeposit

Stores an individual Synth deposit on sale.

Field Type Description
user address The depositor.
amount uint The quantity of oUSD deposited.

Variables


oikos

The address of the main Oikos contract; the depot contains OKS.

Type: Oikos public


synth

The address of the oUSD Synth, which are the synth held in the depot.

Type: Synth public


feePool

The address of the FeePool contract. Since transfer fees were eliminated in SIP-19, this is not really used anymore. All the fee pool functions this contract calls have now been replaced with effective no-ops.

Type: FeePool public


fundsWallet

The address where ether and synths raised by selling OKS are sent.

It is also where ether is sent if the proceeds of a sale of synths could not be transferred because the recipient is a non-payable contract.

Type: address public


oracle

The address which provides the usd prices of OKS and ether. This is not the same oracle address as in ExchangeRates.

Type: address public


ORACLE_FUTURE_LIMIT

The oracle can submit prices no more than ten minutes into the future.

Type: uint public constant

Value: 10 minutes


priceStalePeriod

It is assumed the known price is out of date if it is older than this. Initialised to 3 hours.

Type: uint public


lastPriceUpdateTime

The last time usdToSnxPrice and usdToEthPrice were updated by the oracle calling updatePrices.

Type: uint public


usdToSnxPrice

The price of OKS in USD.

Type: uint public (18 decimals)


usdToEthPrice

The price of BNB in USD.

Type: uint public (18 decimals)


deposits

Users can deposit oUSD to be sold on the depot. This variable holds the queue of open deposits, which are sold in the order they were deposited.

This queue is stored as an "array" within a mapping: the keys are array indices. Deposits are stored by a contiguous block of keys between depositStartIndex (inclusive) and depositEndIndex (exclusive).

A mapping is used instead of an array in order to avoid having to copy entries around when deposits are deleted, which saves on gas. When a deposit is made it is added to the end of the list, and when a deposit is filled, it is removed from the start of the list. Thus over time the list of deposits slides down the set of array indexes, but the address space of the mapping is large enough that it will never be filled.

Type: mapping(uint => synthDeposit) public


depositStartIndex

The index of the next deposit to be processed in the deposits queue.

Type: uint public


depositEndIndex

The index one past the last deposit in the deposits queue.

Type: uint public


totalSellableDeposits

The total quantity of oUSD currently in the deposits queue to be purchased.

Type: uint public (18 decimals)


minimumDepositAmount

The minimum oUSD quantity required for a deposit to be added to the queue. Initialised to 50.0.

Type: uint public (18 decimals)


smallDeposits

Deposits of less than minimumDepositAmount oUSD are not placed on the deposits queue. Instead, they are kept here so that the depositor can withdraw them.

Type: mapping(address => uint) public (18 decimals)


Functions


constructor

Initialises the various addresses this contract knowws, along with the initial prices and the inherited SelfDestructible and Pausable instances.

Details

Signature

constructor(address _owner, address _fundsWallet, Oikos _oikos, Synth _synth, FeePool _feePool, address _oracle, uint _usdToEthPrice, uint _usdToSnxPrice) public

Superconstructors


setFundsWallet

Allows the owner to set the fundsWallet address.

Details

Signature

setFundsWallet(address _fundsWallet) external

Modifiers

Emits


setOracle

Allows the owner to set the oracle address.

Details

Signature

setOracle(address _oracle) external

Modifiers

Emits


setSynth

Allows the owner to set the address of the synth contract the depot knows about.

Details

Signature

setSynth(Synth _synth) external

Modifiers

Emits


setOikos

Allows the owner to set the address of the oikos contract.

Details

Signature

setOikos(Synthetix _oikos)

Modifiers

Emits


setPriceStalePeriod

Allows the owner to set the stale period for depot prices.

Details

Signature

setPriceStalePeriod(uint _time)

Modifiers

Emits


setMinimumDepositAmount

Allows the owner to set the minimum deposit amount.

Details

Signature

setMinimumDepositAmount(uint _amount)

Modifiers

Preconditions

  • _amount must be greater than UNIT.

Emits


updatePrices

Allows the oracle address to update the USD BNB and OKS prices known to the depot.

The prices are accompanied by the time they were sent. The oracle will not accept updates that are not the most recent, otherwise which protects from accepting stale prices during network congestion.

Details

Signature

updatePrices(uint newEthPrice, uint newOikosPrice, uint timeSent) external

Modifiers

Preconditions

Emits


() (fallback function)

This simply calls exchangeEtherForSynths so that if ether is sent to the contract, it is automatically exchanged for synths.

Details

Signature

() external payable


exchangeEtherForSynths

Sells oUSD to callers who send ether. The synths are sold from the deposits queue in the order they were deposited.

Purchased quantity: msg.value * usdToEthPrice

Each deposit is sold in turn until the full This function if invoked with a

Requires that the contract is not paused, and that the prices are not stale.

Returns the number of oUSD exchanged. Converts any ether sent to the contract to a quantity of synths at current prices. Fulfils this quantity by iterating through the deposit queue until the entire quantity is found. If a given deposit is insufficient to cover the entire requested amount, it is exhausted and removed from the queue. For each deposit found, the proper quantity of ether is sent to the depositor. If the quantity could not be sent because the target is a non-payable contract, then it is remitted to fundsWallet. Then send the Synths to the recipient. If the whole quantity could not be fulfilled, then the remaining ether is refunded to the purchaser.

  • exchangeEtherForSynths() returns (uint):

exchangeEtherForSynthsAtRate

  • exchangeEtherForSynthsAtRate(uint guaranteedRate) returns (uint): Allows the caller to specify the current price, and then calls to exchangeEtherForSynths. Reverts if the current price does not match the price provided as an argument. This is intended as a protection against front-running by the contract owner, or otherwise a case where a price update is in flight at the invocation time.

exchangeEtherForOikos

  • exchangeEtherForOikos() returns (uint): Requires that the contract is not paused, and that the prices are not stale. Converts the received ether to a quantity of OKS with oikosReceivedForEther. Sends the ether to fundsWallet, sends the converted quantity of OKS to the message sender from the contract's own reserves. Returns the OKS quantity sent. If the contract has insufficient OKS, then the transfer will fail and the transaction will revert.

exchangeEtherForOikosAtRate

  • exchangeEtherForOikosAtRate(uint guaranteedEtherRate, uint guaranteedSynthetixRate) returns (uint): As exchangeEtherForSynthsAtRate is to exchangeEtherForSynths, this is to exchangeEtherForSynthetix.

exchangeSynthsForOikos

  • exchangeSynthsForOikos(uint synthAmount) returns (uint): Identical to exchangeEtherForSynthetix, but perform the price conversion with oikosReceivedForSynths. The amount of synths to send is provided as a function argument, and then transferred to fundsWallet with transferFrom, so this function requires the caller to have approved the depot contract to make such a withdrawal. Note that this assumes that oUSD is worth exactly one dollar.

exchangeSynthsForOikosAtRate

  • exchangeSynthsForOikosAtRate(uint synthAmount, uint guaranteedRate) returns (uint): As per exchangeEtherForSynthetixAtRate.

withdrawOikos

  • withdrawOikos(uint amount): Only callable by the contract owner. Allows the owner to transfer OKS out of the Depot to themselves.

withdrawMyDepositedSynths

  • withdrawMyDepositedSynths(): Withdraws all Synths deposited by the message sender. Iterates through the entire deposit queue; if for a given entry the message sender is the depositor, delete that deposit and and add the deposited quantity of tokens to the pile to be remitted. Then transfer this quantity back to the message sender, along with any tokens in smallDeposits.

depositSynths

  • depositSynths(uint amount): Just an alias to synth.transferFrom(msg.sender, this, amount). This requires the sender to have approved the deposit.

tokenFallback

  • tokenFallback(address from, uint amount, bytes data) returns (bool): Only callable by the synth contract. Handles the actual deposit flow whenever synths are sent to this contract. If the transferred quantity is smaller than the minimum deposit amount, add it to the sender's small deposit balance. Otherwise, "append" the deposit to the deposit queue/mapping and update total sellable deposit quantity.

pricesAreStale

True if usdToSnxPrice and usdToEthPrice are too old to be considered usably up to date.

That is, they are considered stale if lastPriceUpdateTime is more than priceStalePeriod seconds in the past.

If prices are stale, then the depot's exchange functionality is disabled. This is because attackers can profitably exploit the contract if the prices known on chain do not reflect the true state of the world closely enough.

Details

Signature

pricesAreStale() public view returns (bool)


oikosReceivedForSynths

Computes the quantity of OKS received in exchange for a given quantity of oUSD at current prices, assuming oUSD are worth $1. This is equivalent to:

Q_\text{OKS} = Q_\text{oUSD} \times \frac{1}{\pi_\text{OKS}}
Details

Signature

oikosReceivedForSynths(uint amount) public view returns (uint)


oikosReceivedForEther

Computes the quantity of OKS received in exchange for a given quantity of Ether at current prices. This is equivalent to:

Q_\text{OKS} = Q_\text{BNB} \times \frac{\pi_\text{ETH}}{\pi_\text{OKS}}
Details

Signature

oikosReceivedForEther(uint amount) public view returns (uint)


synthsReceivedForEther

Computes the quantity of oUSD received in exchange for a given quantity of BNB at current prices. This is equivalent to:

Q_\text{oUSD} = Q_\text{BNB} \times \pi_\text{OKS}
Details

Signature

synthsReceivedForEther(uint amount) public view returns (uint)


Modifiers


onlyOracle

Reverts the transaction if msg.sender is not the oracle address.


onlySynth

Reverts the transaction if msg.sender is not the synth address.


pricesNotStale

Reverts the transaction if pricesAreStale returns false, because the contract's known prices are too old to safely use.


Events


FundsWalletUpdated

  • FundsWalletUpdated(address newFundsWallet)

OracleUpdated

  • OracleUpdated(address newOracle)

SynthUpdated

  • SynthUpdated(Synth newSynthContract)

OikosUpdated

  • OikosUpdated(Synthetix newSynthetixContract)

PriceStalePeriodUpdated

  • PriceStalePeriodUpdated(uint priceStalePeriod)

PricesUpdated

  • PricesUpdated(uint newEthPrice, uint newOikosPrice, uint timeSent)

Exchange

  • Exchange(string fromCurrency, uint fromAmount, string toCurrency, uint toAmount)

SynthWithdrawal

  • SynthWithdrawal(address user, uint amount)

SynthDeposit

  • SynthDeposit(address indexed user, uint amount, uint indexed depositIndex)

SynthDepositRemoved

  • SynthDepositRemoved(address indexed user, uint amount, uint indexed depositIndex)

SynthDepositNotAccepted

  • SynthDepositNotAccepted(address user, uint amount, uint minimum)

SynthDepositAmountUpdated

  • MinimumDepositAmountUpdated(uint amount)

NonPayableContract

  • NonPayableContract(address indexed receiver, uint amount)

ClearedDeposit

  • ClearedDeposit(address indexed fromAddress, address indexed toAddress, uint fromBNBAmount, uint toAmount, uint indexed depositIndex)