# Oracle

An Oracle contract that collects price reports from several feeds and ensures they are within a price range and time limit. &#x20;

## Structs

### <mark style="color:blue;">**Oracle**</mark>

```rust
 struct Oracle<phantom Witness: drop> has key, store {
    id: UID,
    // Set of module Witnesses that are allowed to report prices.
    feeds: VecSet<TypeName>,
    // Reported prices must have a timestamp earlier than `current_timestamp - time_limit`. 
    // It is in milliseconds. 
    time_limit: u64,
    // Reported prices must be within the following range: `leader_price + deviation % >= reported_price >= leader_price - deviation %`.
    deviation: u256
  }  
```

* **feeds** - Set of module Witnesses that are allowed to report prices.
* **time\_limit** - Reported prices must have a timestamp earlier than \`current\_timestamp - time\_limit\`. It is in milliseconds.
* **deviation** **-** Reported prices must be within the following range: \`leader\_price + deviation % >= reported\_price >= leader\_price - deviation %\`.

### <mark style="color:blue;">**Report**</mark>

```rust
struct Report has store, copy, drop {
    price: u256,
    timestamp: u64
 }
```

* **price** - Price has 18 decimals.
* **timestamp -** Timestamp in milliseconds.&#x20;

### <mark style="color:blue;">**Price**</mark>

```rust
struct Price {
    // `sui::object::ID` of the`Oracle` this request was sent from.
    oracle: ID,
    // The first reported price. 
    // Price has 18 decimals.  
    price: u256,
    // It is always 18.  
    decimals: u8, 
    // The price was reported at this time.  
    timestamp: u64    
 }
```

* **oracle -** the \`sui::object::ID\` of the Oracle this request was sent from.
* **price -** The first reported price after all checks.&#x20;
* **decimals -** It is always 18.
* **timestamp -** The time at which this price was reported.&#x20;

## Interface

### <mark style="color:blue;">new</mark>

**Creates an `Oracle` with a set of feeds.**

```rust
public fun new<Witness: drop>(
  cap: &mut OwnerCap<Witness>,
  wit: Witness, 
  feeds: vector<TypeName>, 
  time_limit: u64, 
  deviation: u256, 
  ctx: &mut TxContext
): Oracle<Witness>
```

* **@param cap:** An owner cap from `suitears::owner`. This `OwnerCap` will be the owner of the new `Oracle`.
* **@param wit:** A Witness from the module that will manage this `Oracle`.
* **@param feeds:** Feed Witnesses. Only modules in the `Oracle.feeds` can report a price in the `Request` hot potato.
* **@param time\_limit:** A time in milliseconds that determines how old a price timestamp can be.
* **@param deviation:** A percentage that determines an acceptable price range for all reported prices.
* **@return** Oracle\<Witness>.

**Aborts**

* `feeds` vector has repeated values.
* `time_limit` must be higher than 0 milliseconds.
* `deviation` must be higher than 0.

### <mark style="color:blue;">share</mark>

**Shares the `Oracle` object.**

```rust
public fun share<Witness: drop>(self: Oracle<Witness>)
```

* **@param self:** The `Oracle`.

### <mark style="color:blue;">request</mark>

**Creates a `Request` hot potato.**

```rust
public fun request<Witness: drop>(self: &Oracle<Witness>): Request
```

* **@param self:** The `Request` will require all feeds from `Oracle` to be reported.
* **@return** `Request`.

**Aborts**

* `self.feed` is empty.

### <mark style="color:blue;">report</mark>

**Adds a price `Report` to the `Request`.**

```rust
public fun report<Witness: drop>(request: &mut Request, _: Witness, timestamp: u64, price: u128, decimals: u8)
```

* **@param request:** `Request` hot potato.
* **@param \_ :** A Witness to verify the reporters.
* **@param timestamp:** The timestamp of the price feed.
* **@param price:** The price
* **@param decimals**: The decimal houses of the `price` value.
* **@return** `Request`.

**Aborts**

* a feed reports more than once.

### <mark style="color:blue;">destroy\_request</mark>

**Destroy the `Request` potato and verify the price values and timestamps.**

```rust
public fun destroy_request<Witness: drop>(self: &Oracle<Witness>, request: Request, c: &Clock): Price
```

* **@param self:** The `Oracle` that the `Request` was sent from.
* **@param request:** The `Request`.
* **@param c:** The shared `sui::clock::Clock` object.
* **@return** `Price`.

**Aborts**

* The`Request.oracle` does not match the `self.id`.
* The number of reports does not match the number of feeds in the `Oracle.feeds`.
* The report witnesses do not match the required feed witnesses.
* The reported price is outside the `time_limit`.
* The price falls outside the outside `deviation` range.

### <mark style="color:blue;">destroy\_price</mark>

**Destroys an `Oracle` object.**

```rust
public fun destroy_oracle<Witness: drop>(self: Oracle<Witness>)
```

* **@param self:** The `Oracle` that the `Request` was sent from.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.

**Aborts**

* the `cap` is not the owner of `self`.

### <mark style="color:blue;">feeds</mark>

**Returns a vector of the `Oracle.feeds`.**

```rust
public fun feeds<Witness: drop>(self: &Oracle<Witness>): vector<TypeName>
```

* **@param self:** An `Oracle` object.
* **@return** vector

### <mark style="color:blue;">feeds</mark>

**Returns a vector of the `Oracle.feeds`.**

```rust
public fun feeds<Witness: drop>(self: &Oracle<Witness>): vector<TypeName>
```

* **@param self:** An `Oracle` object.
* **@return** vector

### <mark style="color:blue;">time\_limit</mark>

**Returns a time limit set in the `Oracle`.**

```rust
public fun feeds<Witness: drop>(self: &Oracle<Witness>): vector<TypeName>
```

* **@param self:** An `Oracle` object.
* **@return** vector

### <mark style="color:blue;">deviation</mark>

**Returns the price deviation set in the `Oracle`.**

```rust
public fun deviation<Witness: drop>(self: &Oracle<Witness>): u256
```

* **@param self:** An `Oracle` object.
* **@return u**256

### <mark style="color:blue;">uid</mark>

**Allows extensions to read dynamic fields.**

```rust
public fun uid<Witness: drop>(self: &Oracle<Witness>): &UID
```

* **@param self:** An `Oracle` object.
* **@return** `sui::object::UID`

### <mark style="color:blue;">oracle</mark>

**Returns the `sui::object::ID` of a Price's oracle.**

```rust
public fun oracle(price: &Price): ID
```

* **@param price:** A `Price` potato.
* **@return** `sui::object::ID`

### <mark style="color:blue;">price</mark>

**Returns the price value of a `Price` hot potato.**

```rust
public fun price(price: &Price): u256
```

* **@param price:** A `Price` potato.
* **@return** u256

### <mark style="color:blue;">decimals</mark>

**Returns the decimal houses of the price value.**

```rust
public fun decimals(price: &Price): u8
```

* **@param price:** A `Price` potato.
* **@return** u8

### <mark style="color:blue;">timestamp</mark>

**Returns the timestamp of the a `Price`.**

```rust
public fun timestamp(price: &Price): u64
```

* **@param price:** A `Price` potato.
* **@return** u64

### <mark style="color:blue;">uid\_mut</mark>

**Allows extensions to add/remove dynamic fields.**

```rust
public fun uid_mut<Witness: drop>(self: &mut Oracle<Witness>, cap: &OwnerCap<Witness>): &mut UID
```

* **@param self:** An `Oracle` object.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.
* **@return** `sui::object::UID`

**Aborts**

* The `cap` is not the owner of `self`.

### <mark style="color:blue;">add</mark>

**Adds a feed Witness to an `Oracle`.**

```rust
public fun add<Witness: drop>(self: &mut Oracle<Witness>, cap: &OwnerCap<Witness>, feed: TypeName)
```

* **@param self:** An `Oracle` object.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.
* **@param feed:** A Witness feed.

**Aborts**

* The `cap` is not the owner of `self`.
* A duplicated `feed` is added.

### <mark style="color:blue;">remove</mark>

**Removes a feed Witness to an `Oracle`.**

```rust
public fun remove<Witness: drop>(self: &mut Oracle<Witness>, cap: &OwnerCap<Witness>, feed: TypeName)
```

* **@param self:** An `Oracle` object.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.
* **@param feed:** A Witness feed.

**Aborts**

* The `cap` is not the owner of `self`.
* The `Oracle` has 1 feed left.

### <mark style="color:blue;">update\_time\_limit</mark>

**Updates the time\_limit of an `Oracle`.**

```rust
public fun update_time_limit<Witness: drop>(self: &mut Oracle<Witness>, cap: &OwnerCap<Witness>, time_limit: u64)
```

* **@param self:** An `Oracle` object.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.
* **@param time\_limit:** The new time\_limit.

**Aborts**

* The `cap` is not the owner of `self`.
* The `time_limit` cannot be zero.

### <mark style="color:blue;">update\_deviation</mark>

**Updates the deviation of an `Oracle`.**

```rust
public fun update_deviation<Witness: drop>(self: &mut Oracle<Witness>, cap: &OwnerCap<Witness>, deviation: u256)
```

* **@param self:** An `Oracle` object.
* **@param cap:** The `suitears::owner::OwnerCap` that owns the `self`.
* **@param deviation:** The new deviation.

**Aborts**

* The `cap` is not the owner of `self`.
* The `time_limit` cannot be zero.

### <mark style="color:blue;">new\_price\_for\_testing</mark>

**Creates a `Price` for testing purposes only. Only available in tests.**

```rust
#[test_only]
public fun new_price_for_testing(
 oracle: ID,
 price: u256,
 decimals: u8,
 timestamp: u64
): Price
```

* **@param oracle:** `sui::object::ID` of the`Oracle` this request was sent from.
* **@param price:** The reported price.
* **@param decimals:** The decimals precision of `price`.
* **@param timestamp:** The timestamp in milliseconds in which the price was recorded.
