Skip to content

Commit

Permalink
test(reward-distributor): Add simple sucessful test
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmDreamy committed Jul 22, 2024
1 parent 92c908c commit 0b1dcb4
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 15 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ env:
ARBITRUM_PROVIDER_URL: https://1rpc.io/arb
OPTIMISM_PROVIDER_URL: https://endpoints.omniatech.io/v1/op/mainnet/public
MAINNET_PROVIDER_URL: https://eth.llamarpc.com
ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}
ZEROX_API_KEY: ${{ secrets.ZEROX_API_KEY }}

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: foundry-rs/foundry-toolchain@v1
- uses: oven-sh/setup-bun@v2
- run: bun install
- uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-
- run: bun install --frozen-lockfile
- run: bun run lint:ci
- run: bun test
- run: bun run test
Binary file modified bun.lockb
Binary file not shown.
26 changes: 14 additions & 12 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import "@gelatonetwork/web3-functions-sdk/hardhat-plugin";
import "@nomiclabs/hardhat-ethers";
import "@foundry-rs/hardhat-anvil";

const PRIVATE_KEY = process.env.PRIVATE_KEY;
const PRIVATE_KEY =
process.env.PRIVATE_KEY ??
"0x0000000000000000000000000000000000000000000000000000000000000001";

const config = {
w3f: {
Expand All @@ -30,57 +32,57 @@ const config = {
launch: true,
chainId: 1,
forkUrl: "https://rpc.ankr.com/eth",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
ethereum: {
chainId: 1,
url: "https://rpc.ankr.com/eth",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
avalanche: {
url: "https://api.avax.network/ext/bc/C/rpc",
chainId: 43114,
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
arbitrum: {
chainId: 42161,
url: "https://arb1.arbitrum.io/rpc",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
fantom: {
chainId: 250,
url: "https://rpc2.fantom.network",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
optimism: {
chainId: 10,
url: "https://mainnet.optimism.io",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
polygon: {
chainId: 137,
url: "https://rpc-mainnet.maticvigil.com",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
bsc: {
chainId: 56,
url: "https://bsc.publicnode.com",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
kava: {
chainId: 2222,
url: "https://kava-evm.publicnode.com",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
base: {
chainId: 8453,
url: "https://base.meowrpc.com",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
linea: {
chainId: 59144,
url: "https://rpc.linea.build",
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
accounts: [PRIVATE_KEY],
},
},
// biome-ignore lint/complexity/noBannedTypes: Improve auto-completion
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,19 @@
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
"@foundry-rs/easy-foundryup": "^0.1.3",
"@foundry-rs/hardhat-anvil": "^0.1.7",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@tsconfig/recommended": "^1.0.7",
"@types/bun": "latest",
"@viem/anvil": "^0.0.10",
"concurrently": "^8.2.2",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.7.2",
"hardhat": "^2.22.6",
"husky": "^9.1.1",
"lint-staged": "^15.2.7",
"ts-node": "10.9.2",
"type-fest": "^4.23.0",
"typescript": "5.5.3"
},
"dependencies": {
Expand All @@ -91,7 +92,6 @@
"bufferutil",
"core-js",
"core-js-pure",
"cpu-features",
"deno-bin",
"es5-ext",
"esbuild",
Expand Down
169 changes: 169 additions & 0 deletions test/reward-distributor.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import {
afterAll,
afterEach,
beforeAll,
describe,
expect,
test,
} from "bun:test";
import path from "node:path";
import type { JsonRpcProvider } from "@ethersproject/providers";
import type { Anvil } from "@viem/anvil";
import type { Merge } from "type-fest";
import {
type Address,
type Hex,
type PublicClient,
type TestClient,
encodeFunctionData,
parseAbi,
} from "viem";
import { ARBITRUM_OPS_SAFE, ARBITRUM_SPELL } from "../utils/constants";
import { runWeb3Function } from "./utils";
import { setupAnvil } from "./utils/setupAnvil";

const w3fName = "reward-distributor";
const w3fRootDir = path.join("web3-functions");
const w3fPath = path.join(w3fRootDir, w3fName, "index.ts");

describe("Reward Distributor Web3 Function test", () => {
let anvil: Anvil;
let provider: JsonRpcProvider;
let testClient: Omit<Merge<PublicClient, TestClient>, "mode">;
let snapshotId: Hex;

beforeAll(async () => {
({ anvil, provider, testClient, snapshotId } = await setupAnvil({
forkUrl:
"https://rpc.ankr.com/arbitrum/665a6078efb46adbd3eb6b831180fab7d7007c48590f2517e2bce900ba31e8ca",
forkBlockNumber: 234134609n,
}));
});

afterAll(async () => {
await anvil.stop();
});

afterEach(async () => {
await testClient.revert({ id: snapshotId });
});

const run = async () =>
runWeb3Function(
w3fPath,
{
gelatoArgs: {
chainId: (await provider.getNetwork()).chainId,
gasPrice: (await provider.getGasPrice()).toString(),
},
userArgs: {
multiRewardDistributorAddress:
"0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
multiRewardStakingAddresses: [
"0x280c64c4C4869CF2A6762EaDD4701360C1B11F97",
"0xc30911b52b5752447aB08615973e434c801CD652",
],
epochBasedDistributorAddress:
"0x111AbF466654c166Ee4AC15d6A29a3e0625533db",
epochBasedStakingAddresses: [],
},
secrets: {},
storage: {},
},
[provider],
);

test(
"canExec: true - Multiple distributions",
async () => {
const { result } = await run();

expect(result).toEqual({
canExec: true,
callData: [
{
data: "0x63453ae1000000000000000000000000280c64c4c4869cf2a6762eadd4701360c1b11f97",
to: "0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
},
{
data: "0x63453ae1000000000000000000000000c30911b52b5752447ab08615973e434c801cd652",
to: "0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
},
],
});
},
{ timeout: 60000 },
);
test(
"canExec: true - Single distributions",
async () => {
const execAddress =
"0x280c64c4C4869CF2A6762EaDD4701360C1B11F97" as const satisfies Address;
await testClient.sendUnsignedTransaction({
from: ARBITRUM_OPS_SAFE,
to: "0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
data: encodeFunctionData({
abi: parseAbi(["function distribute(address) external"]),
functionName: "distribute",
args: [execAddress],
}),
gasPrice: 0n,
});

const { result } = await run();

expect(result).toEqual({
canExec: true,
callData: [
{
data: "0x63453ae1000000000000000000000000c30911b52b5752447ab08615973e434c801cd652",
to: "0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
},
],
});
},
{ timeout: 60000 },
);
test(
"canExec: false - No distributions to execute",
async () => {
// Increase approval
await testClient.setStorageAt({
address: ARBITRUM_SPELL,
index:
"0xe291b9f68327d6549fd70e333daad56b6cdb38ac27f870dafc9c5d1dcd54d5a5",
value:
"0x0000000000000000000000000000000000000000002116545850052128000000",
});

const execAddresses = [
"0x280c64c4C4869CF2A6762EaDD4701360C1B11F97",
"0xc30911b52b5752447ab08615973e434c801cd652",
] as const satisfies Array<Address>;

await Promise.all(
execAddresses.map(
async (execAddress) =>
await testClient.sendUnsignedTransaction({
from: ARBITRUM_OPS_SAFE,
to: "0xbF5DC3f598AFA173135160CDFce6BFeE45c912eF",
data: encodeFunctionData({
abi: parseAbi(["function distribute(address) external"]),
functionName: "distribute",
args: [execAddress],
}),
gasPrice: 0n,
}),
),
);

const { result } = await run();

expect(result).toEqual({
canExec: false,
message: "No distributions to execute",
});
},
{ timeout: 60000 },
);
});
68 changes: 68 additions & 0 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { JsonRpcProvider } from "@ethersproject/providers";
import type {
MultiChainProviderConfig,
Web3FunctionContextData,
Web3FunctionRunnerOptions,
} from "@gelatonetwork/web3-functions-sdk";
import { Web3FunctionBuilder } from "@gelatonetwork/web3-functions-sdk/builder";
import { Web3FunctionRunner } from "@gelatonetwork/web3-functions-sdk/runtime";

export const MAX_RPC_LIMIT = 100;
export const MAX_DOWNLOAD_LIMIT = 10 * 1024 * 1024;
export const MAX_UPLOAD_LIMIT = 5 * 1024 * 1024;
export const MAX_REQUEST_LIMIT = 100;
export const MAX_STORAGE_LIMIT = 1 * 1024 * 1024;

export const runWeb3Function = async (
web3FunctionPath: string,
context: Web3FunctionContextData<"onRun">,
providers: JsonRpcProvider[],
) => {
const buildRes = await Web3FunctionBuilder.build(web3FunctionPath, {
debug: false,
});

if (!buildRes.success)
throw new Error(`Fail to build web3Function: ${buildRes.error}`);

const runner = new Web3FunctionRunner(false);
const runtime: "docker" | "thread" = "thread";
const memory = buildRes.schema.memory;
const rpcLimit = MAX_RPC_LIMIT;
const timeout = buildRes.schema.timeout * 1000;
const version = buildRes.schema.web3FunctionVersion;

const options: Web3FunctionRunnerOptions = {
runtime,
showLogs: true,
memory,
downloadLimit: MAX_DOWNLOAD_LIMIT,
uploadLimit: MAX_UPLOAD_LIMIT,
requestLimit: MAX_REQUEST_LIMIT,
rpcLimit,
timeout,
storageLimit: MAX_STORAGE_LIMIT,
};
const script = buildRes.filePath;

const multiChainProviderConfig: MultiChainProviderConfig = {};

for (const provider of providers) {
const chainId = (await provider.getNetwork()).chainId;

multiChainProviderConfig[chainId] = provider;
}

const res = await runner.run("onRun", {
script,
context,
options,
version,
multiChainProviderConfig,
});

if (!res.success)
throw new Error(`Fail to run web3 function: ${res.error.message}`);

return res;
};
Loading

0 comments on commit 0b1dcb4

Please sign in to comment.