# Using oracles

{% hint style="info" %}
Use onchain price oracles to get accurate point-in-time USD prices of tokens, without needing to use any offchain price APIs.
{% endhint %}

Without Shadow, augmenting blockchain data with point-in-time accurate prices requires complex data pipelines and integrations with third-party price feed APIs. Shadow drastically simplifies this by allowing you to leverage existing oracle contracts, in <100 lines of code.

In this example, we’ll be updating the 1inch Aggregator contract to emit a shadow event called `OrderFilledDetails` that contains additional metadata of a trade, including the point-in-time USD price of the trade. We’ll be fetching the point-in-time prices via a Chainlink oracle.

## Step 1 – Edit the contract

Open the example on the Shadow Playground: <https://app.shadow.xyz/demo?example=one_inch_oracle>\
\
This will open the playground editor at the 1inch Aggregation Router v5 contract on Ethereum at [`0x1111111254eeb25477b68fb85ed929f73a960582`](https://etherscan.io/address/0x1111111254eeb25477b68fb85ed929f73a960582) (as of Jul 2024).

At L4302, we’ve defined the `OrderFilledDetails` event and a helper `OrderDetails` struct:

```solidity
struct OrderDetails {
    address maker;
    address taker;
    address makerToken;
    address takerToken;
    uint256 takerTokenFilledAmount;
    uint256 makerTokenFilledAmount;
    uint256 orderAmountUsd;
}

event OrderFilledDetails(OrderDetails orderDetails);
```

At L4567, we call a new function called `getOrderAmountUsd` and emit the `OrderFilledDetails` event:

```solidity
uint256 orderAmountUsd = getOrderAmountUsd(order.makerAsset, order.takerAsset, actualMakingAmount, actualTakingAmount);

OrderDetails memory orderDetails = OrderDetails({
    maker: order.maker,
    taker: order.receiver,
    makerToken: order.makerAsset,
    takerToken: order.takerAsset,
    takerTokenFilledAmount: actualTakingAmount,
    makerTokenFilledAmount: actualMakingAmount,
    orderAmountUsd: orderAmountUsd
});

emit OrderFilledDetails(orderDetails);
```

At the bottom of the contract at L4667, we define the `getOrderAmountUsd` function and two other helper functions:

```solidity
function getOrderAmountUsd(address makerToken, address takerToken, uint256 makerTokenAmount, uint256 takerTokenAmount) internal returns (uint256 orderAmountUsd) {
    if (takerToken == address(_WETH)) {
        orderAmountUsd = takerTokenAmount * uint256(getPriceETH()) * 1e6 / 1e18 / 1e8;
    } else if (makerToken == address(_WETH)) {
        orderAmountUsd = makerTokenAmount * uint256(getPriceETH()) * 1e6 / 1e18 / 1e8;
    } else if (isStable(makerToken)) {
        orderAmountUsd = makerTokenAmount * 1e6;
    } else if (isStable(takerToken)) {
        orderAmountUsd = takerTokenAmount * 1e6;
    }

    bool isStable = isStable(makerToken) || isStable(takerToken);
}

function isStable(address token) internal returns (bool) {
    if (
        token == 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 || // USDC
        token == 0xdAC17F958D2ee523a2206206994597C13D831ec7 || // USDT
        token == 0x6B175474E89094C44Da98b954EedeAC495271d0F    // DAI
    ) {
        return true;
    }
    return false;
}

// Get the current price of ETH from Chainlink's ETH/USD oracle (8 decimals)
function getPriceETH() internal view returns (int256) {
    AggregatorV3Interface dataFeed = AggregatorV3Interface(
        0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
    );
    (, int256 answer, , , ) = dataFeed.latestRoundData();
    return answer;
}
```

Notice that we also pasted Chainlink’s `AggregatorV3Interface` into this file. This allows us to call the Chainlink oracle contract via its interface. You’ll have to do this any time you introduce shadow changes that interact with a contract interface that it doesn’t currently interact with.

## Step 2 – Test run your changes

Click “Compile” > “Test Run” in the top right corner, and paste in this transaction hash [`0x045bd6741a5ea38dc6da6b324c2446552bc0e38f6b53b79ada7fc53604135f75`](https://etherscan.io/tx/0x045bd6741a5ea38dc6da6b324c2446552bc0e38f6b53b79ada7fc53604135f75) (or simulate any other order filled transaction).

You should see your custom `OrderFilledDetails` event in the output!

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd5bibBAuYsNZ_0Xxs5zdPgrlS0gXHYUc3QKYyCZ1EJhiy3vdG5rKbHC0qmiCeJKL8W_77eDFi5nM1p8_-7_pNa9fA8YDDUh3O3CB3GRfNsOQDKUWC9JVUwa3hNexouKCCj7GFj6egDxRnxKOW_pmjH90Hy?key=qOOFy18EQhEZbpSRGduGxQ" alt=""><figcaption></figcaption></figure>

## Step 3 – Deploy your changes

If you want to apply these changes on your shadow fork, click the button on the top right corner that says “Apply to your shadow fork”.

This will take you to the editor for your shadow fork, where you can deploy the changes by hitting “Compile > Deploy”


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shadow.xyz/modify-contracts/how-tos/using-oracles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
