Skip to content

Commit

Permalink
feat: add deployment scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
r0ohafza committed Jan 24, 2024
1 parent 362b55b commit d881eeb
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 26 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ To test all packages, run the following command:
To lint all packages, run the following command:

`pnpm lint`

### Deployment

To deploy contracts, please refer to the README in the respective package.
6 changes: 6 additions & 0 deletions packages/splits-v2/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
PRIVATE_KEY=

MAINNET_RPC_URL=
SEPOLIA_RPC_URL=

ETHERSCAN_API_KEY=
59 changes: 44 additions & 15 deletions packages/splits-v2/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
## Splits v2

## Usage

### Build

```shell
$ forge build
```
`pnpm build`

### Test

```shell
$ forge test
```
`pnpm test`

#### Coverage

`pnpm test:coverage`

#### Coverage Report

`pnpm test:coverage:report`

### lint

`pnpm lint`

### Format

```shell
$ forge fmt
```
`pnpm format`

### Deployment

To deploy contracts, please ensure you have the environment variables set in `.env` file. Please refer to `.env.sample`
for the required environment variables.

For a chain not present in .env.sample, add the rpc url and etherscan API key to the .env.sample file and
[foundry.toml](./foundry.toml) file.

To understand how the configuration works, please refer to [foundry docs](https://book.getfoundry.sh/cheatcodes/rpc).

Each contract has its own deployment script. A config file is present in the `config` folder for each chain. The config
files contains the input needed for the constructors of the contracts.

To deploy contracts and verify contracts, run the following command:

#### Splits Warehouse

`pnpm deploy:SplitsWarehouse`

For a test run, use the following command:

`pnpm deploy:SplitsWarehouse:test`

#### Split Factory V2

`pnpm deploy:SplitFactoryV2`

### Gas Snapshots
For a test run, use the following command:

```shell
$ forge snapshot
```
`pnpm deploy:SplitFactoryV2:test`
9 changes: 7 additions & 2 deletions packages/splits-v2/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ solc = "0.8.18"
src = "src"
test = "test"
allow_paths = ['../../node_modules']
fs_permissions = [{ access = "read-write", path = "./" }]


[profile.default.fuzz]
max_test_rejects = 1_000_000
Expand Down Expand Up @@ -62,9 +64,12 @@ targets = [
"src/splitters/SplitWalletV2.sol" = ["SplitWalletV2"]
"src/splitters/SplitFactoryV2.sol" = ["SplitFactoryV2"]


[etherscan]
mainnet = { key = "${API_KEY_ETHERSCAN}" }
mainnet = { key = "${ETHERSCAN_API_KEY}" }
sepolia = { key = "${ETHERSCAN_API_KEY}" }

[rpc_endpoints]
localhost = "http://localhost:8545"
mainnet = "https://eth-mainnet.g.alchemy.com/v2/${API_KEY_ALCHEMY}"
mainnet = "${MAINNET_RPC_URL}"
sepolia = "${SEPOLIA_RPC_URL}"
6 changes: 5 additions & 1 deletion packages/splits-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"format": "prettier --write \"**/*.{json,md,yml}\" --ignore-path=.prettierignore",
"test": "forge test -vvv",
"test:coverage": "forge coverage",
"test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage"
"test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage",
"deploy:SplitsWarehouse:test": "export DRY_RUN=true && source .env && forge script script/SplitsWarehouse.s.sol:SplitsWarehouseScript -vvvvv --rpc-url ",
"deploy:SplitsWarehouse": "export DRY_RUN=false && source .env && forge script script/SplitsWarehouse.s.sol:SplitsWarehouseScript --broadcast --verify -vvvvv --rpc-url ",
"deploy:SplitFactoryV2:test": "export DRY_RUN=true && source .env && forge script script/SplitFactoryV2.s.sol:SplitFactoryV2Script -vvvvv --rpc-url ",
"deploy:SplitFactoryV2": "export DRY_RUN=false && source .env && forge script script/SplitFactoryV2.s.sol:SplitFactoryV2Script --broadcast --verify -vvvvv --rpc-url "
},
"keywords": [],
"author": "@splits",
Expand Down
51 changes: 43 additions & 8 deletions packages/splits-v2/script/Base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@ pragma solidity ^0.8.18;

import { ICreateX } from "./ICreateX.sol";
import { Script } from "forge-std/Script.sol";
import { stdJson } from "forge-std/stdJson.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { LibString } from "solady/utils/LibString.sol";

contract BaseScript is Script {
using stdJson for string;

ICreateX immutable CREATEX = ICreateX(0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed);

function getConfig() internal view returns (string memory) {
string memory inputDir = string.concat(vm.projectRoot(), "/script/config/");
string memory chainDir = string.concat(vm.toString(block.chainid), "/");
string memory file = string.concat("config.json");
return vm.readFile(string.concat(inputDir, chainDir, file));
string memory dir = string.concat(vm.projectRoot(), "/script/config/");
string memory file = string.concat(vm.toString(block.chainid), ".json");
return vm.readFile(string.concat(dir, file));
}

function getAddressFromConfig(string memory _key) internal view returns (address) {
return getConfig().readAddress(_key);
return getConfig().readAddress(string.concat(".", _key));
}

function getStringFromConfig(string memory _key) internal view returns (string memory) {
return getConfig().readString(_key);
return getConfig().readString(string.concat(".", _key));
}

function getUintFromConfig(string memory _key) internal view returns (uint256) {
return getConfig().readUint(_key);
return getConfig().readUint(string.concat(".", _key));
}

function create3(bytes32 salt, bytes memory initCode) internal returns (address) {
Expand All @@ -37,4 +37,39 @@ contract BaseScript is Script {
// keccak256(abi.encodePacked(deployer, hex"01", _salt))
return bytes32(abi.encodePacked(deployer, hex"01", _salt));
}

function updateDeployment(address _contract, string memory _name) internal {
if (isDryRun()) {
return;
}
string memory directory = string.concat(vm.projectRoot(), "/deployments/");
if (!vm.exists(directory)) {
vm.createDir(directory, true);
}

string memory file = string.concat(vm.projectRoot(), "/deployments/", vm.toString(block.chainid), ".json");
bool exists = vm.exists(file);
if (!exists) {
vm.writeFile(file, "{}");
}

string memory json = vm.readFile(file);
if (vm.keyExists(json, string.concat(".", _name))) {
vm.writeJson(LibString.toHexStringChecksummed(_contract), file, string.concat(".", _name));
} else {
string memory root = "root";
vm.serializeJson(root, json);
vm.writeJson(vm.serializeAddress(root, _name, _contract), file);
}
}

function computeCreate3Address(bytes32 salt, address deployer) public view returns (address) {
bytes32 guardedSalt = keccak256(abi.encode(deployer, block.chainid, salt));

return CREATEX.computeCreate3Address(guardedSalt);
}

function isDryRun() internal view returns (bool) {
return vm.envBool("DRY_RUN");
}
}
27 changes: 27 additions & 0 deletions packages/splits-v2/script/SplitFactoryV2.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import { SplitFactoryV2 } from "../src/splitters/SplitFactoryV2.sol";

import { BaseScript } from "./Base.s.sol";
import { console2 } from "forge-std/console2.sol";

contract SplitFactoryV2Script is BaseScript {
uint88 constant DEPLOYMENT_SALT = 1;

function run() public {
address warehouse = getAddressFromConfig("splitsWarehouse");

bytes memory args = abi.encode(warehouse);

uint256 privateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(privateKey);

bytes32 salt = computeSalt(deployer, bytes11(DEPLOYMENT_SALT));

vm.startBroadcast(privateKey);
address factory = create3(salt, abi.encodePacked(type(SplitFactoryV2).creationCode, args));
vm.stopBroadcast();
updateDeployment(factory, "SplitFactoryV2");
}
}
28 changes: 28 additions & 0 deletions packages/splits-v2/script/SplitsWarehouse.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import { SplitsWarehouse } from "../src/SplitsWarehouse.sol";

import { BaseScript } from "./Base.s.sol";
import { console2 } from "forge-std/console2.sol";

contract SplitsWarehouseScript is BaseScript {
uint88 constant DEPLOYMENT_SALT = 0;

function run() public {
string memory name = getStringFromConfig("nativeTokenName");
string memory symbol = getStringFromConfig("nativeTokenSymbol");

bytes memory args = abi.encode(name, symbol);

uint256 privateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(privateKey);

bytes32 salt = computeSalt(deployer, bytes11(DEPLOYMENT_SALT));

vm.startBroadcast(privateKey);
address warehouse = create3(salt, abi.encodePacked(type(SplitsWarehouse).creationCode, args));
vm.stopBroadcast();
updateDeployment(warehouse, "SplitsWarehouse");
}
}
4 changes: 4 additions & 0 deletions packages/splits-v2/script/config/1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"nativeTokenName": "Splits Wrapped Ether",
"nativeTokenSymbol": "SplitsETH"
}
4 changes: 4 additions & 0 deletions packages/splits-v2/script/config/11155111.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"nativeTokenName": "Splits Wrapped Ether",
"nativeTokenSymbol": "SplitsETH"
}

0 comments on commit d881eeb

Please sign in to comment.