-
Notifications
You must be signed in to change notification settings - Fork 1
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
Add Gelato web3 function deployment script for redstone oracles #208
base: LISK-1155-Set-up-RedStone-Push-Oracle-contracts
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Incede marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { HardhatUserConfig } from "hardhat/config"; | ||
|
||
// PLUGINS | ||
import "@gelatonetwork/web3-functions-sdk/hardhat-plugin"; | ||
import "@nomicfoundation/hardhat-chai-matchers"; | ||
import "@nomiclabs/hardhat-ethers"; | ||
import "@typechain/hardhat"; | ||
import "hardhat-deploy"; | ||
|
||
// Process Env Variables | ||
import * as dotenv from "dotenv"; | ||
dotenv.config({ path: __dirname + "/.env" }); | ||
|
||
const PK = process.env.PK; | ||
const ALCHEMY_ID = process.env.ALCHEMY_ID; | ||
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY; | ||
|
||
// HardhatUserConfig bug | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
const config: HardhatUserConfig = { | ||
// web3 functions | ||
w3f: { | ||
rootDir: "./web3-functions", | ||
debug: false, | ||
networks: ["hardhat", "mumbai"], //(multiChainProvider) injects provider for these networks | ||
}, | ||
// hardhat-deploy | ||
namedAccounts: { | ||
deployer: { | ||
default: 0, | ||
}, | ||
}, | ||
defaultNetwork: "liskSepolia", | ||
|
||
networks: { | ||
hardhat: { | ||
forking: { | ||
url: `https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_ID}`, | ||
blockNumber: 35241432, | ||
}, | ||
}, | ||
|
||
ethereum: { | ||
accounts: PK ? [PK] : [], | ||
chainId: 1, | ||
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, | ||
}, | ||
mumbai: { | ||
accounts: PK ? [PK] : [], | ||
chainId: 80001, | ||
url: `https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_ID}`, | ||
}, | ||
polygon: { | ||
accounts: PK ? [PK] : [], | ||
chainId: 137, | ||
url: "https://polygon-rpc.com", | ||
}, | ||
liskSepolia: { | ||
accounts: PK ? [PK] : [], | ||
chainId: 4202, | ||
url: "https://rpc.sepolia-api.lisk.com", | ||
}, | ||
lisk: { | ||
accounts: PK ? [PK] : [], | ||
chainId: 1135, | ||
url: "https://rpc.api.lisk.com", | ||
}, | ||
}, | ||
|
||
solidity: { | ||
compilers: [ | ||
{ | ||
version: "0.8.18", | ||
settings: { | ||
optimizer: { enabled: true, runs: 200 }, | ||
}, | ||
}, | ||
], | ||
}, | ||
|
||
typechain: { | ||
outDir: "typechain", | ||
target: "ethers-v5", | ||
}, | ||
|
||
// hardhat-deploy | ||
verify: { | ||
etherscan: { | ||
apiKey: ETHERSCAN_API_KEY ? ETHERSCAN_API_KEY : "", | ||
}, | ||
}, | ||
}; | ||
|
||
export default config; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
{ | ||
"name": "lens-ai-poc", | ||
"version": "0.0.1", | ||
"description": "Smart Oracle that pushes prices online every hour or when the price difference with the last price is greater or equal than 2%", | ||
"scripts": { | ||
"build": "yarn install && yarn compile && npx tsc", | ||
"clean": "yarn hardhat clean && rm -rf node_modules && rm -rf dist", | ||
"compile": "npx hardhat compile --force", | ||
Incede marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"deploy": "npx hardhat deploy", | ||
"test": "npx hardhat test --network liskSepolia", | ||
"format": "prettier --write '*/**/*.*{js,json,md,ts}'", | ||
"format:check": "prettier --check '*/**/*.*{js,json,md,ts}'", | ||
"tinker": "npx hardhat run scripts/tinker.ts", | ||
"lint": "eslint --cache . && yarn lint:sol", | ||
"lint:ts": "eslint -c .eslintrc.json --ext \"**/*.ts\" \"**/*.test.ts\"", | ||
"lint:sol": "solhint 'contracts/**/*.sol'", | ||
"postinstall": "yarn husky install", | ||
"w3f:deploy": "npx w3f deploy web3-functions/index.ts", | ||
"w3f:test": "npx w3f test web3-functions/index.ts --logs --chain-id=4202" | ||
}, | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@ethersproject/providers": "5.7.2", | ||
"@gelatonetwork/automate-sdk": "^2.7.0-beta", | ||
"@gelatonetwork/web3-functions-sdk": "^2.0.3", | ||
"@nomicfoundation/hardhat-chai-matchers": "1.0.6", | ||
"@nomicfoundation/hardhat-network-helpers": "^1.0.8", | ||
"@nomiclabs/hardhat-ethers": "2.2.3", | ||
"@openzeppelin/contracts-upgradeable": "4.8.3", | ||
"@tsconfig/recommended": "1.0.2", | ||
"@typechain/ethers-v5": "^10.2.1", | ||
"@typechain/hardhat": "6.1.6", | ||
"@types/chance": "1.1.3", | ||
"@types/mocha": "^10.0.1", | ||
"@types/node": "16.7.10", | ||
"@types/uuid": "9.0.1", | ||
"@typescript-eslint/eslint-plugin": "4.30.0", | ||
"@typescript-eslint/parser": "4.30.0", | ||
"chai": "4.3.7", | ||
"dotenv": "10.0.0", | ||
"eslint": "7.32.0", | ||
"eslint-config-prettier": "8.3.0", | ||
"eslint-plugin-prettier": "4.0.0", | ||
"ethers": "5.7.2", | ||
"hardhat": "2.14.0", | ||
"hardhat-contract-sizer": "2.8.0", | ||
"hardhat-deploy": "0.11.29", | ||
"husky": "8.0.3", | ||
"lint-staged": "11.1.2", | ||
"prettier": "2.8.8", | ||
"prettier-plugin-solidity": "1.1.3", | ||
"rxjs": "7.8.1", | ||
"solhint": "3.4.1", | ||
"solhint-plugin-prettier": "0.0.5", | ||
"ts-node": "10.9.1", | ||
"typechain": "^8.1.1", | ||
"typescript": "5.0.4" | ||
}, | ||
"lint-staged": { | ||
"*.*{js,json,md,ts,yml,yaml}": "prettier --write", | ||
"*.*{ts,js}": "eslint -c .eslintrc.json" | ||
}, | ||
"dependencies": { | ||
"@openzeppelin/contracts": "^4.9.0", | ||
"@redstone-finance/evm-connector": "^0.0.22" | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Requirements are:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Gelato dashboard has the option to trigger w3f function based on time interval or onchain events. So one way to achieve the 1st bullet point would be deploy a contract that checks and compares the prices from our oracle and source and triggers an onchain event that could be consumed by Gelato API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we use like it's currently implemented
to get live and stored price and compare them to see if update is needed? For 6 hours interval, we'll probably need to store timestamp of last price update and compare it each time w3f is executed to check if it's more than 6 hours from last price update. w3f will always be executed every 30 or 60 seconds (we still need to decide on this). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay I understand what you mean now. Your previous comment implied that the code must trigger w3f once certain conditions are met. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. W3f will be executed every 30 or 60 seconds. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { | ||
Web3Function, | ||
Web3FunctionContext, | ||
} from "@gelatonetwork/web3-functions-sdk"; | ||
import { BigNumber, Contract } from "ethers"; | ||
import { WrapperBuilder } from "@redstone-finance/evm-connector"; | ||
|
||
const ORACLE_ABI = [ | ||
"function getStoredPrice() public view returns (uint256)", | ||
"function getLivePrice() public view returns (uint256)", | ||
"function getPriceDeviation() external view returns (uint)", | ||
"function decimals() external pure returns (uint8)", | ||
"function updatePrice() public", | ||
]; | ||
|
||
Web3Function.onRun(async (context: Web3FunctionContext) => { | ||
const { userArgs, multiChainProvider } = context; | ||
|
||
const provider = multiChainProvider.default(); | ||
|
||
const oracleAddress = userArgs.oracleAddress as string; | ||
const oracle = new Contract(oracleAddress, ORACLE_ABI, provider); | ||
|
||
// Wrap contract with redstone data service | ||
const wrappedOracle = WrapperBuilder.wrap(oracle).usingDataService( | ||
{ | ||
dataServiceId: "redstone-rapid-demo", | ||
uniqueSignersCount: 1, | ||
dataFeeds: ["LSK"], | ||
disablePayloadsDryRun: true, | ||
}, | ||
["https://d33trozg86ya9x.cloudfront.net"] | ||
); | ||
|
||
// Retrieve stored & live prices | ||
const decimals = await wrappedOracle.decimals(); | ||
const livePrice: BigNumber = await wrappedOracle.getLivePrice(); | ||
const storedPrice: BigNumber = await wrappedOracle.getStoredPrice(); | ||
console.log(`Live price: ${livePrice.toString()}`); | ||
console.log(`Stored price: ${storedPrice.toString()}`); | ||
|
||
// Check price deviation | ||
const deviation: BigNumber = await wrappedOracle.getPriceDeviation(); | ||
const deviationPrct = (deviation.toNumber() / 10 ** decimals) * 100; | ||
console.log(`Deviation: ${deviationPrct.toFixed(2)}%`); | ||
|
||
// Only update price if deviation is above 0.2% | ||
const minDeviation = 0.2; | ||
if (deviationPrct < minDeviation) { | ||
return { | ||
canExec: false, | ||
message: `No update: price deviation too small`, | ||
}; | ||
} | ||
|
||
// Craft transaction to update the price on-chain | ||
const { data } = await wrappedOracle.populateTransaction.updatePrice(); | ||
return { | ||
canExec: true, | ||
callData: [{ to: oracleAddress, data: data as string }], | ||
}; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"web3FunctionVersion": "2.0.0", | ||
"runtime": "js-1.0", | ||
"memory": 128, | ||
"timeout": 30, | ||
"userArgs": { | ||
"currency": "string", | ||
"oracleAddress": "string" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"currency":"LSK", | ||
"oracleAddress":"0x198549B829ba2Cc8c203247f25c3b3bC33df6304" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this URL be different than what is
L2_RPC_URL
? Can we just useL2_RPC_URL
without having a new one?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general it would be same. I am not sure where or which library picks this env var and we might have to change the lib code so maybe better to keep it separate (for now)