From d2944b8e72f0b7050ae03425619f8e3b0b61f49e Mon Sep 17 00:00:00 2001 From: Danil Kovtonyuk Date: Fri, 26 Feb 2021 19:52:15 +1000 Subject: [PATCH] update price oracle --- abis/MultiCall.abi.json | 22 +++++++++++++++++++ abis/OffchainOracle.abi.json | 12 +++++++++++ abis/PriceOracle.abi.json | 28 ------------------------ src/config.js | 3 ++- src/priceWatcher.js | 42 +++++++++++++++++++++++++++++------- 5 files changed, 70 insertions(+), 37 deletions(-) create mode 100644 abis/MultiCall.abi.json create mode 100644 abis/OffchainOracle.abi.json delete mode 100644 abis/PriceOracle.abi.json diff --git a/abis/MultiCall.abi.json b/abis/MultiCall.abi.json new file mode 100644 index 0000000..fa6dc92 --- /dev/null +++ b/abis/MultiCall.abi.json @@ -0,0 +1,22 @@ +[ + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "internalType": "struct MultiCall.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "multicall", + "outputs": [ + { "internalType": "bytes[]", "name": "results", "type": "bytes[]" }, + { "internalType": "bool[]", "name": "success", "type": "bool[]" } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/OffchainOracle.abi.json b/abis/OffchainOracle.abi.json new file mode 100644 index 0000000..e5b971d --- /dev/null +++ b/abis/OffchainOracle.abi.json @@ -0,0 +1,12 @@ +[ + { + "inputs": [ + { "internalType": "contract IERC20", "name": "srcToken", "type": "address" }, + { "internalType": "contract IERC20", "name": "dstToken", "type": "address" } + ], + "name": "getRate", + "outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/PriceOracle.abi.json b/abis/PriceOracle.abi.json deleted file mode 100644 index 76c5c60..0000000 --- a/abis/PriceOracle.abi.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "constant": true, - "inputs": [ - { - "internalType": "contract IERC20[]", - "name": "fromTokens", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "oneUnitAmounts", - "type": "uint256[]" - } - ], - "name": "getPricesInETH", - "outputs": [ - { - "internalType": "uint256[]", - "name": "prices", - "type": "uint256[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } -] diff --git a/src/config.js b/src/config.js index 4393e02..be0c5a4 100644 --- a/src/config.js +++ b/src/config.js @@ -8,7 +8,8 @@ module.exports = { httpRpcUrl: process.env.HTTP_RPC_URL, wsRpcUrl: process.env.WS_RPC_URL, oracleRpcUrl: process.env.ORACLE_RPC_URL || 'https://mainnet.infura.io/', - oracleAddress: '0xA2b8E7ee7c8a18ea561A5CF7C9C365592026E374', + offchainOracleAddress: '0x080ab73787a8b13ec7f40bd7d00d6cc07f9b24d0', + multiCallAddress: '0xda3c19c6fe954576707fa24695efb830d9cca1ca', aggregatorAddress: process.env.AGGREGATOR, minerMerkleTreeHeight: 20, privateKey: process.env.PRIVATE_KEY, diff --git a/src/priceWatcher.js b/src/priceWatcher.js index a0c1630..4f187f9 100644 --- a/src/priceWatcher.js +++ b/src/priceWatcher.js @@ -1,20 +1,46 @@ const Redis = require('ioredis') -const { redisUrl, oracleAddress, oracleRpcUrl } = require('./config') +const { redisUrl, offchainOracleAddress, multiCallAddress, oracleRpcUrl } = require('./config') const { getArgsForOracle, setSafeInterval } = require('./utils') const redis = new Redis(redisUrl) const Web3 = require('web3') const web3 = new Web3(oracleRpcUrl) -const priceOracleABI = require('../abis/PriceOracle.abi.json') -const oracle = new web3.eth.Contract(priceOracleABI, oracleAddress) +const multiCallABI = require('../abis/MultiCall.abi.json') +const offchainOracleABI = require('../abis/OffchainOracle.abi.json') + +const offchainOracle = new web3.eth.Contract(offchainOracleABI) +const multiCall = new web3.eth.Contract(multiCallABI, multiCallAddress) const { tokenAddresses, oneUintAmount, currencyLookup } = getArgsForOracle() +const { toBN } = require('web3-utils') + async function main() { - const prices = await oracle.methods.getPricesInETH(tokenAddresses, oneUintAmount).call() - const ethPrices = prices.reduce((acc, price, i) => { - acc[currencyLookup[tokenAddresses[i]]] = price - return acc - }, {}) + const callData = tokenAddresses.map(address => ({ + to: offchainOracleAddress, + data: offchainOracle.methods + .getRate( + address, + '0x0000000000000000000000000000000000000000', // rate to ETH + ) + .encodeABI(), + })) + + const { results, success } = await multiCall.methods.multicall(callData).call() + + const ethPrices = {} + for (let i = 0; i < results.length; i++) { + if (!success[i]) { + continue + } + + const decodedRate = web3.eth.abi.decodeParameter('uint256', results[i]).toString() + const numerator = toBN(oneUintAmount[i]) + const denominator = toBN(10).pow(toBN(18)) // eth decimals + const price = toBN(decodedRate).mul(numerator).div(denominator) + + ethPrices[currencyLookup[tokenAddresses[i]]] = price.toString() + } + await redis.hmset('prices', ethPrices) console.log('Wrote following prices to redis', ethPrices) }