Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade velo spot oracle #171

Merged
merged 16 commits into from
Feb 7, 2025
Merged
292 changes: 292 additions & 0 deletions src/abis/velo_spot_price_oracle.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
[
{
"inputs": [
{ "internalType": "contract MultiWrapper", "name": "_multiWrapper", "type": "address" },
{ "internalType": "contract IOracle[]", "name": "existingOracles", "type": "address[]" },
{ "internalType": "enum OffchainOracle.OracleType[]", "name": "oracleTypes", "type": "uint8[]" },
{ "internalType": "contract IERC20[]", "name": "existingConnectors", "type": "address[]" },
{ "internalType": "contract IERC20", "name": "wBase", "type": "address" },
{ "internalType": "address", "name": "owner_", "type": "address" }
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{ "inputs": [], "name": "ArraysLengthMismatch", "type": "error" },
{ "inputs": [], "name": "ConnectorAlreadyAdded", "type": "error" },
{ "inputs": [], "name": "InvalidOracleTokenKind", "type": "error" },
{ "inputs": [], "name": "MathOverflowedMulDiv", "type": "error" },
{ "inputs": [], "name": "OracleAlreadyAdded", "type": "error" },
{
"inputs": [{ "internalType": "address", "name": "owner", "type": "address" }],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [{ "internalType": "address", "name": "account", "type": "address" }],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{ "inputs": [], "name": "SameTokens", "type": "error" },
{ "inputs": [], "name": "TooBigThreshold", "type": "error" },
{ "inputs": [], "name": "UnknownConnector", "type": "error" },
{ "inputs": [], "name": "UnknownOracle", "type": "error" },
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "ConnectorAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "ConnectorRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract MultiWrapper", "name": "multiWrapper", "type": "address" }
],
"name": "MultiWrapperUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{
"indexed": false,
"internalType": "enum OffchainOracle.OracleType",
"name": "oracleType",
"type": "uint8"
}
],
"name": "OracleAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{
"indexed": false,
"internalType": "enum OffchainOracle.OracleType",
"name": "oracleType",
"type": "uint8"
}
],
"name": "OracleRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" },
{ "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [{ "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "addConnector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{ "internalType": "enum OffchainOracle.OracleType", "name": "oracleKind", "type": "uint8" }
],
"name": "addOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "connectors",
"outputs": [{ "internalType": "contract IERC20[]", "name": "allConnectors", "type": "address[]" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20[]", "name": "srcTokens", "type": "address[]" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getManyRatesToEthWithCustomConnectors",
"outputs": [{ "internalType": "uint256[]", "name": "weightedRates", "type": "uint256[]" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20[]", "name": "srcTokens", "type": "address[]" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getManyRatesWithCustomConnectors",
"outputs": [{ "internalType": "uint256[]", "name": "weightedRates", "type": "uint256[]" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20[]", "name": "srcTokens", "type": "address[]" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "contract IOracle[]", "name": "customOracles", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getManyRatesWithCustomConnectorsAndOracles",
"outputs": [{ "internalType": "uint256[]", "name": "weightedRates", "type": "uint256[]" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" }
],
"name": "getRate",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "bool", "name": "useSrcWrappers", "type": "bool" }
],
"name": "getRateToEth",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "bool", "name": "useSrcWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getRateToEthWithCustomConnectors",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "bool", "name": "useSrcWrappers", "type": "bool" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getRateToEthWithThreshold",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getRateWithCustomConnectors",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "contract IERC20[]", "name": "customConnectors", "type": "address[]" },
{ "internalType": "contract IOracle[]", "name": "customOracles", "type": "address[]" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getRateWithCustomConnectorsAndOracles",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" },
{ "internalType": "uint256", "name": "thresholdFilter", "type": "uint256" }
],
"name": "getRateWithThreshold",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "multiWrapper",
"outputs": [{ "internalType": "contract MultiWrapper", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "oracles",
"outputs": [
{ "internalType": "contract IOracle[]", "name": "allOracles", "type": "address[]" },
{ "internalType": "enum OffchainOracle.OracleType[]", "name": "oracleTypes", "type": "uint8[]" }
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "removeConnector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{ "internalType": "enum OffchainOracle.OracleType", "name": "oracleKind", "type": "uint8" }
],
"name": "removeOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" },
{
"inputs": [{ "internalType": "contract MultiWrapper", "name": "_multiWrapper", "type": "address" }],
"name": "setMultiWrapper",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
3 changes: 2 additions & 1 deletion src/hooks/useEarnStrategies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ export function useEarnStrategies() {
const veloStrategies = useMemo(() => {
if (!veloPrices || !veloData) return []
const temp: Strategy[] = []
for (const pool of veloData) {
// Filter out SAIL
for (const pool of veloData.filter((p) => p.address != '0xB5cD4bD4bdB5C97020FBE192258e6F08333990E2')) {
const rewards = REWARDS.velodrome[pool.address.toLowerCase()]
if (!rewards) continue // filter out any extra pools that may be fetched

Expand Down
45 changes: 25 additions & 20 deletions src/providers/VelodromePriceProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { type DispatchWithoutAction, createContext, useContext, useEffect, useReducer, useState } from 'react'

import type { ReactChildren, SummaryItemValue } from '~/types'
import oracleAbi from '~/abis/velo_oracle.abi.json'
// import oracleAbi from '~/abis/velo_oracle.abi.json'
import veloSpotOracleAbi from '~/abis/velo_spot_price_oracle.abi.json'
import { useContract } from '~/hooks'
import { formatSummaryValue } from '~/utils'
import { formatUnits } from 'ethers/lib/utils'

const oracleContractAddress = '0x395942c2049604a314d39f370dfb8d87aac89e16'
// const oracleContractAddress = '0x395942c2049604a314d39f370dfb8d87aac89e16'
const veloSpotOracleContractAddress = '0x59114D308C6DE4A84F5F8cD80485a5481047b99f'

const priceAddresses = {
VELO: '0x9560e827af36c94d2ac33a39bce1fe78631088db',
// OP: '0x4200000000000000000000000000000000000042',
// WETH: '0x4200000000000000000000000000000000000006',
// SNX: '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4',
HAI: '0x10398AbC267496E49106B07dd6BE13364D10dC71',
SUSD: '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9',
KITE: '0xf467C7d5a4A9C4687fFc7986aC6aD5A4c81E1404',
PXETH: '0x300d2c875C6fb8Ce4bf5480B4d34b7c9ea8a33A4',
SAIL: '0x7a1263eC3Bf0a19e25C553B8A2C312e903262C5E',
WSTETH: '0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb',
// SAIL: '0x7a1263eC3Bf0a19e25C553B8A2C312e903262C5E',
DINERO: '0x09D9420332bff75522a45FcFf4855F82a0a3ff50',
}

Expand Down Expand Up @@ -45,33 +52,30 @@ export function VelodromePriceProvider({ children }: Props) {
const [error, setError] = useState('')
const [refresher, refetchPrices] = useReducer((x) => x + 1, 0)

const velodromeOracleContract = useContract(oracleContractAddress, oracleAbi)
// const velodromeOracleContract = useContract(oracleContractAddress, oracleAbi)
const veloSpotOracleContract = useContract(veloSpotOracleContractAddress, veloSpotOracleAbi)

useEffect(() => {
if (!velodromeOracleContract) return
if (!veloSpotOracleContract) return

const usdcDst = '0x0b2c639c533813f4aa9d7837caf62653d097ff85'

let isStale = false
const fetchData = async () => {
try {
setLoading(true)
const addresses = Object.values(priceAddresses)
const prices = (await velodromeOracleContract.getManyRatesWithConnectors(addresses.length, [
...addresses,
'0x4200000000000000000000000000000000000042', // connector OP
'0x4200000000000000000000000000000000000006', // connector WETH
'0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // connector sUSD
'0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb', // connector wstETH
'0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', // connector SNX
'0x7a1263eC3Bf0a19e25C553B8A2C312e903262C5E', // connector SAIL
'0x300d2c875C6fb8Ce4bf5480B4d34b7c9ea8a33A4', // connector pxETH
'0x09D9420332bff75522a45FcFf4855F82a0a3ff50', // connector DINERO
'0x0b2c639c533813f4aa9d7837caf62653d097ff85', // denomination USDC
])) as string[] // actually BigNumber[] but don't need to import
const prices = (await veloSpotOracleContract.getManyRatesWithCustomConnectors(
[...addresses],
usdcDst,
true,
[],
10
)) as string[] // actually BigNumber[] but don't need to import
if (isStale) return

const formattedPrices = prices.reduce(
(obj, price, i) => {
;(obj as any)[Object.keys(priceAddresses)[i]] = formatSummaryValue(formatUnits(price, 18), {
;(obj as any)[Object.keys(priceAddresses)[i]] = formatSummaryValue(formatUnits(price, 6), {
style: 'currency',
minDecimals: 2,
maxDecimals: 2,
Expand All @@ -81,6 +85,7 @@ export function VelodromePriceProvider({ children }: Props) {
},
{} as VelodromePriceContext['prices']
)

setPrices(formattedPrices)
} catch (error: any) {
console.error(error)
Expand All @@ -94,7 +99,7 @@ export function VelodromePriceProvider({ children }: Props) {
return () => {
isStale = true
}
}, [velodromeOracleContract, refresher])
}, [veloSpotOracleContract, refresher])

return (
<VelodromePriceContext.Provider
Expand Down
Loading