Skip to content

Commit

Permalink
update to pricelib v1.3.1 but add ignorelist config, and change oracl…
Browse files Browse the repository at this point in the history
…e count, slowing down the syncing but improving accuracy
  • Loading branch information
nemani committed Jul 20, 2023
1 parent 7e8ea90 commit 74e0144
Show file tree
Hide file tree
Showing 27 changed files with 1,596 additions and 513 deletions.
75 changes: 65 additions & 10 deletions subgraphs/polygon-bridge/src/prices/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Configuration

In `subgraph.yaml`, add the following code snippet inside the `abis` section of the `datasources` which is going to fetch prices of token using the `Price Oracle`.
</br>
**NOTE**: Include the following code snippet in each of the datasources, that is dependent on the `Price Oracle` and update imports in each file inside oracle folder.

```
Expand Down Expand Up @@ -46,9 +47,21 @@ Following are some ways through which you can get the prices of tokens:

```
import { BigDecimal } from "@graphprotocol/graph-ts";
import { getUsdPricePerToken, getUsdPrice } from "../Oracle";
import { getUsdPrice, getUsdPricePerToken, getLiquidityBoundPrice } from "../Oracle";
// Method 1
// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal
let tokenPrice = getUsdPrice(tokenAddr, amount);
```

> Note: Preferred as it internally calls `getLiquidityBoundPrice(...)` and returns token price bounded by it's pool's liquidity.
> </br>
> To get the price per token, you can still use `getUsdPrice(...)` as:
> </br></br> > `let tokenPrice = getUsdPrice(tokenAddr, BIGDECIMAL_ONE);`
```
// Method 2
// Using function getUsdPricePerToken(tokenAddr: Address): CustomPriceType
let tokenPrice: BigDecimal;
Expand All @@ -57,18 +70,33 @@ let fetchPrice = getUsdPricePerToken(tokenAddr);
// fetchPrice.reverted: Bool
// fetchPrice.usdPrice: BigDecimal
// fetchPrice.decimals: number
tokenPrice = fetchPrice.usdPrice * amount
// Method 2
// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal
let tokenPrice = getUsdPrice(tokenAddr, amount);
// fetchPrice.oracleType: string
// fetchPrice.liquidity: BigDecimal
if (!fetchPrice.reverted) {
if (
fetchPrice.oracleType == constants.OracleType.UNISWAP_FORKS_ROUTER ||
fetchPrice.oracleType == constants.OracleType.CURVE_ROUTER
) {
fetchPrice = getLiquidityBoundPrice(tokenAddr, fetchPrice, amount)
}
tokenPrice = fetchPrice.usdPrice * amount
}
```

## Optimizations

- Reorder the methods present in `index.ts`, depending on which method works best for you.
- Configure default `number of oracles` to fetch price from and their `order of preference` in OracleType's constructor, depending on which oracles _generally_ works best for you.
- Although querying multiple oracles for the same token's price mean more contract calls, this overhead can be beared for smaller subgraphs, and for specific tokens/block ranges for larger ones in favour of spotting and ignoring outlier values by avoiding complete reliance on a single source of truth and trusting the closer majority values, especially for low/distributed liquidity tokens, or during volatile markets.
</br></br>
The result is an average price on the k-closest reported values.
</br>
where, `k = ceil(reportedPrices.length/2)`
- For any observed pricing discrepancies, you may define an override on the default oracle configuration in network's config file which works better for the mispriced token(s).
</br>
An example override is defined under `ORACLE CONFIG OVERRIDES` section in `config/template.ts`
</br></br>
Any new overrides shall be maintained in both the subgraph as well as the reference pricelib directory, so the same inconsistencies do not have to be handled separately.

## Folder Structure

Expand All @@ -86,13 +114,17 @@ Prices
│ ├── aurora.ts
│ ├── avalanche.ts
│ ├── bsc.ts
│ ├── celo.ts
│ ├── cronos.ts
│ ├── fantom.ts
│ ├── fuse.ts
│ ├── gnosis.ts
│ ├── harmony.ts
│ ├── mainnet.ts
│ ├── moonbeam.ts
│ ├── optimism.ts
│ └── polygon.ts
│ ├── polygon.ts
│ └── template.ts
├── oracles
│ ├── AaveOracle.ts
│ ├── ChainLinkFeed.ts
Expand Down Expand Up @@ -154,6 +186,21 @@ Prices
| | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | `6810080` ||
| | `0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F` | `586899` ||

### Celo

| **Method** | **Address** | **StartBlock** | **MultiCall** |
| ------------ | :------------------------------------------: | :------------: | :-----------: |
| UniswapForks | | | |
| | `0xe3d8bd6aed4f159bc8000a9cd47cffdb95f96121` | `5272598` ||
| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `7254057` ||

### Cronos

| **Method** | **Address** | **StartBlock** | **MultiCall** |
| ------------ | :------------------------------------------: | :------------: | :-----------: |
| UniswapForks | | | |
| | `0x145863eb42cf62847a6ca784e6416c1682b1b2ae` | `5247` ||

### Fantom

| **Method** | **Address** | **StartBlock** | **MultiCall** |
Expand All @@ -169,6 +216,14 @@ Prices
| | `0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52` | `4250168` ||
| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `2457904` ||

### Fuse

| **Method** | **Address** | **StartBlock** | **MultiCall** |
| ------------ | :------------------------------------------: | :------------: | :-----------: |
| UniswapForks | | | |
| | `0xe3f85aad0c8dd7337427b9df5d0fb741d65eeeb5` | `15645719` ||
| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `12936314` ||

### Gnosis

| **Method** | **Address** | **StartBlock** | **MultiCall** |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
import * as utils from "../common/utils";
import * as constants from "../common/constants";
import { CustomPriceType } from "../common/types";
import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts";
import { CustomPriceType, OracleContract } from "../common/types";
import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts";
import { CalculationsCurve as CalculationsCurveContract } from "../../../generated/FxERC20Events/CalculationsCurve";

export function getCalculationsCurveContract(
contractAddress: Address
contract: OracleContract,
block: ethereum.Block | null = null
): CalculationsCurveContract | null {
if (utils.isNullAddress(contractAddress)) return null;
if (
(block && contract.startBlock.gt(block.number)) ||
utils.isNullAddress(contract.address)
)
return null;

return CalculationsCurveContract.bind(contractAddress);
return CalculationsCurveContract.bind(contract.address);
}

export function getTokenPriceUSDC(tokenAddr: Address): CustomPriceType {
export function getTokenPriceUSDC(
tokenAddr: Address,
block: ethereum.Block | null = null
): CustomPriceType {
const config = utils.getConfig();

if (!config || config.curveCalculationsBlacklist().includes(tokenAddr))
return new CustomPriceType();

const calculationCurveContract = getCalculationsCurveContract(
config.curveCalculations()
config.curveCalculations(),
block
);
if (!calculationCurveContract) return new CustomPriceType();

Expand All @@ -32,6 +41,7 @@ export function getTokenPriceUSDC(tokenAddr: Address): CustomPriceType {

return CustomPriceType.initialize(
tokenPrice,
constants.DEFAULT_USDC_DECIMALS
constants.DEFAULT_USDC_DECIMALS,
constants.OracleType.CURVE_CALCULATIONS
);
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
import * as utils from "../common/utils";
import * as constants from "../common/constants";
import { CustomPriceType } from "../common/types";
import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts";
import { CustomPriceType, OracleContract } from "../common/types";
import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts";
import { CalculationsSushiSwap as CalculationsSushiContract } from "../../../generated/FxERC20Events/CalculationsSushiSwap";

export function getSushiSwapContract(
contractAddress: Address
contract: OracleContract,
block: ethereum.Block | null = null
): CalculationsSushiContract | null {
if (utils.isNullAddress(contractAddress)) return null;
if (
(block && contract.startBlock.gt(block.number)) ||
utils.isNullAddress(contract.address)
)
return null;

return CalculationsSushiContract.bind(contractAddress);
return CalculationsSushiContract.bind(contract.address);
}

export function getTokenPriceUSDC(tokenAddr: Address): CustomPriceType {
export function getTokenPriceUSDC(
tokenAddr: Address,
block: ethereum.Block | null = null
): CustomPriceType {
const config = utils.getConfig();

if (!config || config.sushiCalculationsBlacklist().includes(tokenAddr))
return new CustomPriceType();

const sushiContract = getSushiSwapContract(config.sushiCalculations());
if (!sushiContract) {
return new CustomPriceType();
}
const calculationSushiContract = getSushiSwapContract(
config.sushiCalculations(),
block
);
if (!calculationSushiContract) return new CustomPriceType();

const tokenPrice: BigDecimal = utils
.readValue<BigInt>(
sushiContract.try_getPriceUsdc(tokenAddr),
calculationSushiContract.try_getPriceUsdc(tokenAddr),
constants.BIGINT_ZERO
)
.toBigDecimal();

return CustomPriceType.initialize(
tokenPrice,
constants.DEFAULT_USDC_DECIMALS
constants.DEFAULT_USDC_DECIMALS,
constants.OracleType.SUSHI_CALCULATIONS
);
}
21 changes: 20 additions & 1 deletion subgraphs/polygon-bridge/src/prices/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,30 @@ export namespace NULL {
export const TYPE_ADDRESS = Address.fromString(TYPE_STRING);
}

export namespace OracleType {
export const AAVE_ORACLE = "AaveOracle";
export const CURVE_ROUTER = "CurveRouter";
export const CHAINLINK_FEED = "ChainlinkFeed";
export const YEARN_LENS_ORACLE = "YearnLensOracle";
export const CURVE_CALCULATIONS = "CurveCalculations";
export const UNISWAP_FORKS_ROUTER = "UniswapForksRouter";
export const SUSHI_CALCULATIONS = "SushiswapCalculations";
}

export const CHAIN_LINK_USD_ADDRESS = Address.fromString(
"0x0000000000000000000000000000000000000348"
);

export const PRICE_LIB_VERSION = "1.1.0";
export const PRICE_LIB_VERSION = "1.3.1";

export const INT_ZERO = 0 as i32;
export const INT_ONE = 1 as i32;
export const INT_TWO = 2 as i32;
export const INT_THREE = 3 as i32;
export const INT_FOUR = 4 as i32;
export const INT_FIVE = 5 as i32;
export const INT_SIX = 6 as i32;
export const INT_NEGATIVE_ONE = -1 as i32;

export const BIGINT_ZERO = BigInt.fromI32(0);
export const BIGINT_ONE = BigInt.fromI32(1);
Expand Down
Loading

0 comments on commit 74e0144

Please sign in to comment.