Skip to content

Commit

Permalink
better foundry profile & faster tests
Browse files Browse the repository at this point in the history
  • Loading branch information
erhant committed Dec 24, 2024
1 parent 8441365 commit f43b764
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 134 deletions.
7 changes: 0 additions & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@
},
"solidity.formatter": "forge",
"solidity.defaultCompiler": "localFile",
// remappings.txt here fixes random errors
"solidity.remappingsUnix": [
"forge-std/=lib/forge-std/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/"
],
"material-icon-theme.files.associations": {
".gas-snapshot": "bench-ts"
}
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,16 @@ forge script ./script/Deploy.s.sol:Upgrade<CONTRACT_NAME> \
Run tests on local network:
```sh
forge test
FOUNDRY_PROFILE=test forge test
# or -vvv to show reverts in detail
forge test -vvv
FOUNDRY_PROFILE=test forge test -vvv
```
or fork an existing chain and run the tests on it:

```sh
forge test --rpc-url <RPC_URL>
FOUNDRY_PROFILE=test forge test --rpc-url <RPC_URL>
```

### Code Coverage
Expand Down
113 changes: 76 additions & 37 deletions docs/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,28 @@ forge install
Compile the contracts with:

```sh
forge clean && forge build
forge build
```

### Upgradability

We are using [openzeppelin-foundry-upgrades](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) library. To make sure upgrades are **safe**, you must do one of the following (as per their [docs](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades?tab=readme-ov-file#before-running)) before you run `forge script` or `forge test`:

- `forge clean` beforehand, e.g. `forge clean && forge test`
- include `--force` option when running, e.g. `forge test --force`

> [!NOTE]
>
> Note that for some users this may fail (see [issue](https://github.com/firstbatchxyz/dria-oracle-contracts/issues/16)) due to a missing NPM package called `@openzeppelin/upgrades-core`. To fix it, do:
> We are using [openzeppelin-foundry-upgrades](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) library, which [requires](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades?tab=readme-ov-file#before-running) clean-up per compilation to ensure upgrades are done safely. We use `force = true` option in `foundry.toml` for this, which may increase build times.
>
> Note that for some users this may fail (see [issue](https://github.com/firstbatchxyz/dria-oracle-contracts/issues/16)) due to a missing NPM package called `@openzeppelin/upgrades-core`. To fix it, you can install the package manually:
>
> ```sh
> npm install @openzeppelin/upgrades-core@latest -g
> ```
> [!TIP]
>
> If at any point the submodules become "dirty" (e.g. there are local changes that you are unaware of) you can do:
>
> ```sh
> git submodule deinit -f .
> git submodule update --init --recursive --checkout
> ```
### Updates
To update contracts to the latest library versions, use:
Expand All @@ -75,7 +79,10 @@ forge update

### Setup

To be able to use our contracts, we need an [Ethereum Wallet](#create-wallet), and an [RPC endpoint](#prepare-rpc-endpoint).
To be able to deploy & use our contracts, we need two things:

- [Ethereum Wallet](#create-wallet)
- [RPC endpoint](#prepare-rpc-endpoint)

### Create Wallet

Expand Down Expand Up @@ -107,96 +114,128 @@ To interact with the blockchain, we require an RPC endpoint. You can get one fro

You will use this endpoint for the commands that interact with the blockchain, such as deploying and upgrading; or while doing fork tests.

### Deploy & Verify Contract
### Deploy Contract

Deploy the contract with:

```sh
forge clean && forge script ./script/Deploy.s.sol:Deploy<CONTRACT_NAME> \
forge script ./script/Deploy.s.sol:Deploy<CONTRACT_NAME> \
--rpc-url <RPC_URL> \
--account <WALLET_NAME> \
--broadcast
```

You can see deployed contract addresses under the `deployment/<chainid>.json`
You can see deployed contract addresses under the [`deployments/<chainid>.json`](./deployments/) folder.

You can verify the contract during deployment by adding the verification arguments as well:
You will need the contract ABIs to interact with them as well, thankfully there is a nice short-hand command to export that:

```sh
forge clean && forge script ./script/Deploy.s.sol:Deploy<CONTRACT_NAME> \
forge inspect <CONTRACT_NAME> abi > ./deployments/abis/<CONTRACT_NAME>.json
```

### Verify Contract

Verification requires the following values, based on which provider you are using:

- **Provider**: can accept any of `etherscan`, `blockscout`, `sourcify`, `oklink` or `custom` for more fine-grained stuff.
- **URL**: based on the chosen provider, we require its URL as well, e.g. `https://base-sepolia.blockscout.com/api/` for `blockscout` on Base Sepolia
- **API Key**: an API key from the chosen provider, must be stored as `ETHERSCAN_API_KEY` in environment no matter whicih provider it is!.

You can actually verify the contract during deployment by adding the verification arguments as well:

```sh
forge script ./script/Deploy.s.sol:Deploy<CONTRACT_NAME> \
--rpc-url <RPC_URL> \
--account <WALLET_NAME> \
--broadcast \
--verify --verifier blockscout \
--verifier-url <VERIFIER_URL>
```

You can verify an existing contract with:
Alternatively, you can verify an existing contract (perhaps deployed from a factory) with:

```sh
forge verify-contract <CONTRACT_ADDRESS> src/<CONTRACT_NAME>.sol:<CONTRACT_NAME> \
--verifier blockscout \
--verifier-url <VERIFIER_URL>
forge verify-contract <CONTRACT_ADDRESS> ./src/<CONTRACT_NAME>.sol:<CONTRACT_NAME> \
--verifier blockscout --verifier-url <VERIFIER_URL>
```

Note that the `--verifier-url` value should be the target explorer's homepage URL. Foundry will read your `ETHERSCAN_API_KEY` from environment already, so this does not have to be within your URL.
### Upgrade Contract

`https://base-sepolia.blockscout.com/api/` for `Base Sepolia Network`
Upgrading an existing contract is done as per the instructions in [openzeppelin-foundry-upgrades](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) repository.

First, we create a new contract with its name as `ContractNameV2`, and then we execute the following command:

```sh
forge script ./script/Deploy.s.sol:Upgrade<CONTRACT_NAME> \
--rpc-url <RPC_URL> \
--account <WALLET_NAME> --broadcast \
--sender <WALLET_ADDRESS> \
--verify --verifier blockscout \
--verifier-url <VERIFIER_URL>
```

> [!NOTE]
>
> The `--verifier` can accept any of the following: `etherscan`, `blockscout`, `sourcify`; but we are using Blockscout most of the time.
> The `--sender <ADDRESS>` field is mandatory when deploying a contract, it can be obtained with the command below, which will prompt for keystore password:
>
> ```sh
> cast wallet address --account <WALLET_NAME>
> ```
## Testing & Diagnostics
Run tests on local network:
```sh
forge clean && forge test
FOUNDRY_PROFILE=test forge test
# or -vvv to show reverts in detail
forge clean && forge test -vvv
FOUNDRY_PROFILE=test forge test -vvv
```
or fork an existing chain and run the tests on it:

```sh
forge clean && forge test --rpc-url <RPC_URL>
FOUNDRY_PROFILE=test forge test --rpc-url <RPC_URL>
```

### Code Coverage

We have a script that generates the coverage information as an HTML page. This script requires [`lcov`](https://linux.die.net/man/1/lcov) and [`genhtml`](https://linux.die.net/man/1/genhtml) command line tools. To run, do:

```sh
forge clean && ./coverage.sh
./coverage.sh
```

Alternatively, you can see a summarized text-only output as well:

```sh
forge clean && forge coverage --no-match-coverage "(test|mock|script)"
forge coverage --no-match-coverage "(test|mock|script)"
```

### Storage Layout
### Gas Snapshot

Get storage layout with:
You can examine the gas usage metrics using the command:

```sh
forge clean && ./storage.sh
forge snapshot --snap ./test/.gas-snapshot
```

You can see storage layouts under the storage directory.
You can see the snapshot `.gas-snapshot` file in the current directory.

### Gas Snapshot
### Styling

Take the gas snapshot with:
You can format the contracts with:

```sh
forge clean && forge snapshot
forge fmt ./src/**/*.sol ./script/**/*.sol
```

You can see the snapshot `.gas-snapshot` file in the current directory.
If you have solhint installed, you can lint all contracts with:

```sh
solhint 'src/**/*.sol' 'script/**/*.sol'
```

## Documentation

Expand All @@ -205,10 +244,10 @@ We have auto-generated MDBook documentations under the [`docs`](./docs) folder,
```sh
forge doc

# servers the book as well
# serves the book as well
forge doc --serve
```

## License

We are using Apache-2.0 license.
We are using [Apache-2.0](./LICENSE) license.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleCoordinator
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleCoordinator.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleCoordinator.sol)

**Inherits:**
[LLMOracleTask](/src/LLMOracleTask.sol/interface.LLMOracleTask.md), [LLMOracleManager](/src/LLMOracleManager.sol/abstract.LLMOracleManager.md), UUPSUpgradeable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleManager
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleManager.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleManager.sol)

**Inherits:**
OwnableUpgradeable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleRegistry
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleRegistry.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleRegistry.sol)

**Inherits:**
[Whitelist](/src/Whitelist.sol/abstract.Whitelist.md), UUPSUpgradeable
Expand Down
2 changes: 1 addition & 1 deletion docs/src/src/LLMOracleRegistry.sol/enum.LLMOracleKind.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleKind
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleRegistry.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleRegistry.sol)

The type of Oracle.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/src/LLMOracleTask.sol/interface.LLMOracleTask.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleTask
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleTask.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleTask.sol)

An umbrella interface that captures task-related structs and enums.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LLMOracleTaskParameters
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/LLMOracleTask.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/LLMOracleTask.sol)

Collection of oracle task-related parameters.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/src/Statistics.sol/library.Statistics.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Statistics
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/Statistics.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/Statistics.sol)

Simple statistic library for uint256 arrays.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/src/Whitelist.sol/abstract.Whitelist.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Whitelist
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/4083e0e4f3f5849460fbea5040ecc77651509d1c/src/Whitelist.sol)
[Git Source](https://github.com/firstbatchxyz/dria-oracle-contracts/blob/84413650904832c21815ffefb6eee8517ceb0ffc/src/Whitelist.sol)

**Inherits:**
OwnableUpgradeable
Expand Down
9 changes: 9 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ script = 'script'
cache_path = 'cache'
optimizer = true


# required by upgradability
# see: https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
ffi = true
Expand All @@ -17,6 +18,14 @@ extra_output = ["storageLayout"]
# forces recompilation, required by Upgradable contracts
force = true

# testing does not care about the upgrade checks above
# so we disable them with
[profile.test]
ffi = false
ast = false
build_info = false
force = false

# fs permissions for deployment (false by default)
fs_permissions = [
{ access = "read", path = "out" },
Expand Down
11 changes: 1 addition & 10 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Upgrades, UnsafeUpgrades, Options} from "@openzeppelin/foundry-upgrades/Upgrades.sol";
import {Upgrades, Options} from "@openzeppelin/foundry-upgrades/Upgrades.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {Script} from "forge-std/Script.sol";
import {Vm} from "forge-std/Vm.sol";
Expand Down Expand Up @@ -48,15 +48,6 @@ contract DeployLLMOracleRegistry is Script {

impl = Upgrades.getImplementationAddress(proxy);
}

function deployUnsafe(address impl) external returns (address proxy) {
proxy = UnsafeUpgrades.deployUUPSProxy(
impl,
abi.encodeCall(
LLMOracleRegistry.initialize, (stakes.generator, stakes.validator, token, minRegistrationTimeSec)
)
);
}
}

contract DeployLLMOracleCoordinator is Script {
Expand Down
21 changes: 11 additions & 10 deletions test/LLMOracleCoordinator.t.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Upgrades} from "@openzeppelin/foundry-upgrades/Upgrades.sol";
import {UnsafeUpgrades} from "@openzeppelin/foundry-upgrades/Upgrades.sol";

import {LLMOracleTask, LLMOracleTaskParameters} from "../src/LLMOracleTask.sol";
import {LLMOracleRegistry, LLMOracleKind} from "../src/LLMOracleRegistry.sol";
Expand All @@ -18,19 +18,20 @@ contract LLMOracleCoordinatorTest is Helper {

modifier deployment() {
vm.startPrank(dria);
address registryProxy = Upgrades.deployUUPSProxy(
"LLMOracleRegistry.sol",
abi.encodeCall(
LLMOracleRegistry.initialize, (stakes.generator, stakes.validator, address(token), minRegistrationTime)

oracleRegistry = LLMOracleRegistry(
UnsafeUpgrades.deployUUPSProxy(
address(new LLMOracleRegistry()),
abi.encodeCall(
LLMOracleRegistry.initialize,
(stakes.generator, stakes.validator, address(token), minRegistrationTime)
)
)
);

// wrap proxy with the LLMOracleRegistry contract to use in tests easily
oracleRegistry = LLMOracleRegistry(registryProxy);

// deploy coordinator contract
address coordinatorProxy = Upgrades.deployUUPSProxy(
"LLMOracleCoordinator.sol",
address coordinatorProxy = UnsafeUpgrades.deployUUPSProxy(
address(new LLMOracleCoordinator()),
abi.encodeCall(
LLMOracleCoordinator.initialize,
(
Expand Down
Loading

0 comments on commit f43b764

Please sign in to comment.