From c6586015a089e50cdc973c5955e22a415744fc1f Mon Sep 17 00:00:00 2001 From: yuetloo Date: Thu, 17 Aug 2023 12:29:59 -0400 Subject: [PATCH] add common workspace --- common/.gitignore | 2 + common/README.md | 1 + common/package.json | 28 ++++++++++++++ common/src/block.ts | 20 ++++++++++ common/src/index.ts | 2 + common/src/proof.ts | 85 ++++++++++++++++++++++++++++++++++++++++++ common/tsconfig.json | 22 +++++++++++ contracts/package.json | 1 + 8 files changed, 161 insertions(+) create mode 100644 common/.gitignore create mode 100644 common/README.md create mode 100644 common/package.json create mode 100644 common/src/block.ts create mode 100644 common/src/index.ts create mode 100644 common/src/proof.ts create mode 100644 common/tsconfig.json diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 000000000..e3fbd9833 --- /dev/null +++ b/common/.gitignore @@ -0,0 +1,2 @@ +build +node_modules diff --git a/common/README.md b/common/README.md new file mode 100644 index 000000000..7529c3404 --- /dev/null +++ b/common/README.md @@ -0,0 +1 @@ +# Common clr.fund utility functions used by contracts and vue-app diff --git a/common/package.json b/common/package.json new file mode 100644 index 000000000..039734e11 --- /dev/null +++ b/common/package.json @@ -0,0 +1,28 @@ +{ + "name": "@clrfund/common", + "version": "0.0.1", + "description": "Common utility functions used by clrfund scripts and app", + "main": "src/index", + "scripts": { + "build": "tsc", + "lint": "eslint 'src/**/*.ts'", + "clean": "rm -rf build" + }, + "license": "GPL-3.0", + "devDependencies": { + "eslint": "^8.31.0", + "typescript": "^4.9.3" + }, + "dependencies": { + "ethers": "^5.7.2" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/clrfund/monorepo.git" + }, + "author": "", + "bugs": { + "url": "https://github.com/clrfund/monorepo/issues" + }, + "homepage": "https://github.com/clrfund/monorepo#readme" +} diff --git a/common/src/block.ts b/common/src/block.ts new file mode 100644 index 000000000..e065e146a --- /dev/null +++ b/common/src/block.ts @@ -0,0 +1,20 @@ +import { providers } from 'ethers' + +export interface Block { + blockNumber: number + hash: string + stateRoot: string +} + +/* + * get the block stateRoot using eth_getBlockByHash + */ +export async function getBlock( + blockNumber: number, + provider: providers.JsonRpcProvider +): Promise { + const block = await provider.getBlock(blockNumber) + const blockParams = [block.hash, false] + const rawBlock = await provider.send('eth_getBlockByHash', blockParams) + return { blockNumber, hash: block.hash, stateRoot: rawBlock.stateRoot } +} diff --git a/common/src/index.ts b/common/src/index.ts new file mode 100644 index 000000000..a8f361efc --- /dev/null +++ b/common/src/index.ts @@ -0,0 +1,2 @@ +export * from './block' +export * from './proof' diff --git a/common/src/proof.ts b/common/src/proof.ts new file mode 100644 index 000000000..5cac6127f --- /dev/null +++ b/common/src/proof.ts @@ -0,0 +1,85 @@ +import { utils, providers } from 'ethers' + +/** + * RLP encode the proof returned from eth_getProof + * @param proof proof from the eth_getProof + * @returns + */ +export function rlpEncodeProof(proof: string[]) { + const decodedProof = proof.map((node: string) => utils.RLP.decode(node)) + + return utils.RLP.encode(decodedProof) +} + +/** + * The storage key used in eth_getProof and eth_getStorageAt + * @param account Account address + * @param slotIndex Slot index of the balanceOf storage + * @returns storage key used in the eth_getProof params + */ +export function getStorageKey(account: string, slotIndex: number) { + return utils.keccak256( + utils.concat([ + utils.hexZeroPad(account, 32), + utils.hexZeroPad(utils.hexValue(slotIndex), 32), + ]) + ) +} + +/** + * Get proof from eth_getProof + * @param params Parameter fro eth_getProof + * @returns proof returned from eth_getProof + */ +async function getProof( + params: Array, + provider: providers.JsonRpcProvider +): Promise { + try { + const proof = await provider.send('eth_getProof', params) + return proof + } catch (err) { + console.error( + 'Unable to get proof. Your node may not support eth_getProof. Try a different provider such as Infura', + err + ) + throw err + } +} +/** + * Get the storage proof + * @param token Token contract address + * @param blockHash The block hash to get the proof for + * @param provider provider to connect to the node + * @returns proof returned from eth_getProof + */ +export async function getAccountProof( + token: string, + blockHash: string, + provider: providers.JsonRpcProvider +): Promise { + const params = [token, [], blockHash] + return getProof(params, provider) +} + +/** + * Get the storage proof + * @param token Token contract address + * @param blockHash The block hash to get the storage proof for + * @param userAccount User account to get the proof for + * @param storageSlotIndex The storage index for the balanceOf storage + * @param provider provider to connect to the node + * @returns proof returned from eth_getProof + */ +export async function getStorageProof( + token: string, + blockHash: string, + userAccount: string, + storageSlotIndex: number, + provider: providers.JsonRpcProvider +): Promise { + const storageKey = getStorageKey(userAccount, storageSlotIndex) + + const params = [token, [storageKey], blockHash] + return getProof(params, provider) +} diff --git a/common/tsconfig.json b/common/tsconfig.json new file mode 100644 index 000000000..957cdc1a2 --- /dev/null +++ b/common/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "skipLibCheck": true, + "experimentalDecorators": true, + "alwaysStrict": true, + "noImplicitAny": false, + "forceConsistentCasingInFileNames": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "strict": true, + "outDir": "./build", + "target": "es2018", + "esModuleInterop": true, + "module": "commonjs", + "declaration": true + }, + "exclude": ["node_modules/**"], + "include": ["./src"] +} diff --git a/contracts/package.json b/contracts/package.json index c6c558d39..e2f51762f 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -29,6 +29,7 @@ }, "devDependencies": { "@clrfund/maci-utils": "^0.0.1", + "@clrfund/common": "^0.0.1", "@ethereum-waffle/mock-contract": "^3.4.4", "@kleros/gtcr-encoder": "^1.4.0", "@nomiclabs/hardhat-ethers": "^2.2.1",