An open API service indexing awesome lists of open source software.

https://github.com/firstbatchxyz/swan-contracts

Simulated Worlds with AI Narratives
https://github.com/firstbatchxyz/swan-contracts

agents foundry oracle solidity

Last synced: 3 months ago
JSON representation

Simulated Worlds with AI Narratives

Awesome Lists containing this project

README

          


logo



Swan Protocol



Simulated Worlds with AI Narratives.



License: Apache 2.0


Workflow: Tests


Discord

## Installation

First, make sure you have the requirements:

- We are using [Foundry](https://book.getfoundry.sh/), so make sure you [install](https://book.getfoundry.sh/getting-started/installation) it first.
- Upgradable contracts make use of [NodeJS](https://nodejs.org/en), so you should [install](https://nodejs.org/en/download/package-manager) that as well.

Clone the repository:

```sh
git clone git@github.com:firstbatchxyz/dria-oracle-contracts.git
```

Install dependencies with:

```sh
forge install
```

Compile the contracts with:

```sh
forge build
```

> [!NOTE]
>
> 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:

```sh
forge update
```

## Usage

### Setup

To be able to deploy & use our contracts, we need two things:

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

### Create Wallet

We use keystores for wallet management, with the help of [`cast wallet`](https://book.getfoundry.sh/reference/cast/wallet-commands) command.

Use the command below to create your keystore. The command will prompt for your **private key**, and a **password** to encrypt the keystore itself.

```sh
cast wallet import --interactive
```

> [!WARNING]
>
> Note that you will need to enter the password when you use this keystore.

You can see your keystores under the default directory (`~/.foundry/keystores`) with the command:

```sh
cast wallet list
```

### Prepare RPC Endpoint

To interact with the blockchain, we require an RPC endpoint. You can get one from:

- [Alchemy](https://www.alchemy.com/)
- [Infura](https://www.infura.io/)
- [(see more)](https://www.alchemy.com/best/rpc-node-providers)

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

### Deploy Contract

Deploy the contract with:

```sh
forge script ./script/Deploy.s.sol:Deploy \
--rpc-url \
--account \
--broadcast
```

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

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 inspect abi > ./deployments/abis/.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, its URL, 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 \
--rpc-url \
--account \
--broadcast \
--verify --verifier blockscout \
--verifier-url \
--chain-id 8453
```

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

```sh
forge verify-contract ./src/.sol: \
--verifier blockscout --verifier-url \
--etherscan-api-key --chain-id 8453
```

The chain ID is 8453 for Base Mainnet, and 84532 for Base Sepolia.

### Upgrade Contract

#### Using single-sig wallet
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 \
--rpc-url \
--account --broadcast \
--sender \
--verify --verifier blockscout \
--verifier-url
```

> [!NOTE]
>
> The `--sender

` 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
> ```

#### Using multisig wallet (Our currrent approach with Gnosis Safe multisig)

To upgrade your Swan UUPS contract via a Gnosis multisig, follow these steps:

1. **Deploy the new implementation contract**
Execute the deployment script to get the new implementation address:

```sh
forge script ./script/Deploy.s.sol:DeploySwanImpl \
--rpc-url \
--account --broadcast \
--sender \
--verify --verifier blockscout \
--verifier-url
```

2. **Generate upgrade calldata**

Once you have the new implementation address, generate the calldata for the Gnosis multisig:

```sh
cast calldata "upgradeToAndCall(address,bytes)" 0xNewImplementationAddress 0x
```

This will output something like:
```
0x4f1ef28600000000000000000000000017b6d1eddcd5f9ca19bb2ffed2f3deb6bd74bd2000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000
```

3. **Submit transaction to Gnosis Safe**

Create a new transaction in the Gnosis Safe interface with:
- **To**: Your Swan proxy address
- **Value**: 0 ETH
- **Data**: The calldata generated in step 2

4. **Execute the transaction**

Have the required signers approve the transaction, then execute it to complete the upgrade.

## Testing & Diagnostics

Run tests on local network:

```sh
FOUNDRY_PROFILE=test forge test

# or -vvv to show reverts in detail
FOUNDRY_PROFILE=test forge test -vvv
```

or fork an existing chain and run the tests on it:

```sh
FOUNDRY_PROFILE=test forge test --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
./coverage.sh
```

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

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

### Gas Snapshot

You can examine the gas usage metrics using the command:

```sh
FOUNDRY_PROFILE=test forge snapshot --snap ./test/.gas-snapshot
```

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

### Styling

You can format the contracts with:

```sh
forge fmt ./src/**/*.sol ./script/**/*.sol
```

If you have solhint installed, you can lint all contracts with:

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

## Documentation

We have auto-generated MDBook documentations under the [`docs`](./docs) folder, generated with the following command:

```sh
forge doc

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

## License

We are using [Apache-2.0](./LICENSE) license.