From f6ad5577a8ecac40bb9aa113f42b8a5dce370505 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 00:12:23 +0200 Subject: [PATCH 01/17] delete branching strategy --- CONTRIBUTING.md | 30 ------------------------------ docs/autogen/book.toml | 1 + 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 95b5244..0b0d549 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,12 +3,6 @@ - [Install](#install) - [Pre-commit Hooks](#pre-commit-hooks) - [Requirements for merge](#requirements-for-merge) -- [Branching](#branching) - - [Main](#main) - - [Staging](#staging) - - [Dev](#dev) - - [Feature](#feature) - - [Fix](#fix) - [Code Practices](#code-practices) - [Code Style](#code-style) - [Interfaces](#interfaces) @@ -50,30 +44,6 @@ In order for a PR to be merged, it must pass the following requirements: - The PR must be approved by at least one maintainer - The PR must be approved by 2+ maintainers if the PR is a new feature or > 100 LOC changed -## Branching - -This section outlines the branching strategy of this repo. - -### Main - -The main branch is supposed to reflect the deployed state on all networks. Any pull requests into this branch MUST come from the staging branch. - -### Staging - -The staging branch reflects new code complete deployments or upgrades containing fixes and/or features. Any pull requests into this branch MUST come from the dev branch. The staging branch is used for security audits and deployments. Once the deployment is complete and verified as well as deployment log files are generated, the branch can be merged into main. For more information on the deployment and log file generation check [here](#deployment). - -### Dev - -This is the active development branch. All pull requests into this branch MUST come from fix or feature branches. Upon code completion this branch is merged into staging for auditing and deployment. PRs into this branch should squash all commits into a single commit. - -### Feature - -Any new feature should be developed on a separate branch. The naming convention for these branches is `feat/*`. Once the feature is complete, a pull request into the dev branch can be created. - -### Fix - -Any bug fixes should be developed on a separate branch. The naming convention for these branches is `fix/*`. Once the fix is complete, a pull request into the dev branch can be created. - ## Code Practices ### Code Style diff --git a/docs/autogen/book.toml b/docs/autogen/book.toml index 9ef6709..6654d46 100644 --- a/docs/autogen/book.toml +++ b/docs/autogen/book.toml @@ -6,6 +6,7 @@ title = "" no-section-label = true additional-js = ["solidity.min.js"] additional-css = ["book.css"] +mathjax-support = true git-repository-url = "https://github.com/Uniswap/foundry-template" [output.html.fold] From f6896117d62961d4211ec00fa7777b999ed09cb9 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:13:51 +0200 Subject: [PATCH 02/17] Replace --isolate with annotation --- CONTRIBUTING.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b0d549..23a218c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -105,13 +105,7 @@ New features must be merged with associated tests. Bug fixes should have a corre ### Gas Metering -The [Forge Gas Snapshot](https://github.com/marktoda/forge-gas-snapshot) library is used to measure the gas cost of individual actions. To ensure that the measured gas is accurate, tests have to be run using the isolate argument to generate the correct snapshot and ensure that CI passes: - -```sh -$ forge test --isolate -``` - -When adding new functionality, a new gas snapshot should be added, preferably using `snapLastCall`. +The [Forge Gas Snapshot](https://github.com/marktoda/forge-gas-snapshot) library is used to measure the gas cost of individual actions. Tests that measure gas should be annotated with `/// forge-config: default.isolate = true` and not be fuzzed to ensure that the gas snapshot is accurate and consistent for CI verification. All external functions should have a gas snapshot test, diverging paths within a function should have appropriate gas snapshot tests. ## Deployment From f9708f7dda2d071ef2e80e4c3d98fb9e0448303b Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:17:41 +0200 Subject: [PATCH 03/17] IR compilation and tests --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23a218c..860337b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,7 @@ - [Interfaces](#interfaces) - [NatSpec \& Comments](#natspec--comments) - [Testing](#testing) + - [IR Compilation](#ir-compilation) - [Gas Metering](#gas-metering) - [Deployment](#deployment) - [Deployment](#deployment-1) @@ -103,6 +104,10 @@ Differential testing should be used to compare assembly implementations with imp New features must be merged with associated tests. Bug fixes should have a corresponding test that fails without the bug fix. +### IR Compilation + +When the contracts are compiled via IR, tests should be compiled without IR and the contracts deployed from their bytecode to ensure quick compilation times and bytecode consistency. Check [here](https://github.com/Uniswap/foundry-template/blob/613f81c107cd2885a869dbe4afc1da4f96ed9218/foundry.toml#L22-L28) and [here](https://github.com/Uniswap/foundry-template/blob/main/test/deployers/CounterDeployer.sol) for an example. + ### Gas Metering The [Forge Gas Snapshot](https://github.com/marktoda/forge-gas-snapshot) library is used to measure the gas cost of individual actions. Tests that measure gas should be annotated with `/// forge-config: default.isolate = true` and not be fuzzed to ensure that the gas snapshot is accurate and consistent for CI verification. All external functions should have a gas snapshot test, diverging paths within a function should have appropriate gas snapshot tests. From 42b1295f440c97d67f2c907ad9833bd2f2d00db4 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:18:16 +0200 Subject: [PATCH 04/17] Add link to latest contributing doc --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 860337b..5dff08e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,7 @@ # Contributing +For the latest version of this document, see [here](https://github.com/Uniswap/foundry-template/blob/main/CONTRIBUTING.md). + - [Install](#install) - [Pre-commit Hooks](#pre-commit-hooks) - [Requirements for merge](#requirements-for-merge) From d6377852402283df24faaab65c30f0fbee38dea1 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:21:52 +0200 Subject: [PATCH 05/17] Add link to foundrybook testing section for best practices --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5dff08e..1ce3dc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Interfaces](#interfaces) - [NatSpec \& Comments](#natspec--comments) - [Testing](#testing) + - [Best Practices](#best-practices) - [IR Compilation](#ir-compilation) - [Gas Metering](#gas-metering) - [Deployment](#deployment) @@ -106,6 +107,10 @@ Differential testing should be used to compare assembly implementations with imp New features must be merged with associated tests. Bug fixes should have a corresponding test that fails without the bug fix. +### Best Practices + +Best practices and naming conventions should be followed as outlined in the [Foundry Book](https://getfoundry.sh/forge/tests/overview). + ### IR Compilation When the contracts are compiled via IR, tests should be compiled without IR and the contracts deployed from their bytecode to ensure quick compilation times and bytecode consistency. Check [here](https://github.com/Uniswap/foundry-template/blob/613f81c107cd2885a869dbe4afc1da4f96ed9218/foundry.toml#L22-L28) and [here](https://github.com/Uniswap/foundry-template/blob/main/test/deployers/CounterDeployer.sol) for an example. From d2663ff454fee54e8ba7a74555ea1b07840b0f87 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:25:07 +0200 Subject: [PATCH 06/17] triple slash natspec --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ce3dc6..d38e86e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,7 +97,7 @@ Every contract MUST implement their corresponding interface that includes all ex ### NatSpec & Comments -Interfaces should be the entrypoint for all contracts. When exploring the a contract within the repository, the interface MUST contain all relevant information to understand the functionality of the contract in the form of NatSpec comments. This includes all externally callable functions, errors and events. The NatSpec documentation MUST be added to the functions, errors and events within the interface. This allows a reader to understand the functionality of a function before moving on to the implementation. The implementing functions MUST point to the NatSpec documentation in the interface using `@inheritdoc`. Internal and private functions shouldn't have NatSpec documentation except for `@dev` comments, whenever more context is needed. Additional comments within a function should only be used to give more context to more complex operations, otherwise the code should be kept readable and self-explanatory. +Interfaces should be the entrypoint for all contracts. When exploring the a contract within the repository, the interface MUST contain all relevant information to understand the functionality of the contract in the form of NatSpec comments. This includes all externally callable functions, errors and events. The NatSpec documentation MUST be added to the functions, errors and events within the interface. This allows a reader to understand the functionality of a function before moving on to the implementation. The implementing functions MUST point to the NatSpec documentation in the interface using `@inheritdoc`. Internal and private functions shouldn't have NatSpec documentation except for `@dev` comments, whenever more context is needed. Additional comments within a function should only be used to give more context to more complex operations, otherwise the code should be kept readable and self-explanatory. NatSpec comments should be written with a triple slash (`///`) to ensure compact documentation. ## Testing From 2198230d45854b4656ed64ef8ab2e0a5b6c25182 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:27:30 +0200 Subject: [PATCH 07/17] naming collision avoidance --- CONTRIBUTING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d38e86e..d9df369 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,6 +65,18 @@ The repo follows the official [Solidity Style Guide](https://docs.soliditylang.o } ``` +- Naming collisions should be avoided using a single trailing underscore. + + ```solidity + contract TestContract { + uint256 public foo; + + constructor(uint256 foo_) { + foo = foo_; + } + } + ``` + - Events should generally be emitted immediately after the state change that they represent, and should be named in the past tense. Some exceptions may be made for gas efficiency if the result doesn't affect observable ordering of events. From 3cb1447af87f3bcf088dc6a076857b9d05b8d9e5 Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:34:35 +0200 Subject: [PATCH 08/17] Add section on Solidity versioning --- CONTRIBUTING.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d9df369..be5e81b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Requirements for merge](#requirements-for-merge) - [Code Practices](#code-practices) - [Code Style](#code-style) + - [Solidity Versioning](#solidity-versioning) - [Interfaces](#interfaces) - [NatSpec \& Comments](#natspec--comments) - [Testing](#testing) @@ -103,6 +104,22 @@ The repo follows the official [Solidity Style Guide](https://docs.soliditylang.o - Unchecked arithmetic blocks should contain comments explaining why overflow is guaranteed not to happen or permissible. If the reason is immediately apparent from the line above the unchecked block, the comment may be omitted. +### Solidity Versioning + +Contracts that are meant to be deployed MUST have an explicit version set in the `pragma` statement. + +```solidity +pragma solidity 0.8.X; +``` + +Abstract contracts, libraries and interfaces MUST use the caret (`^`) range operator to specify the version range to ensure better compatibility. + +```solidity +pragma solidity ^0.X.0; +``` + +Libraries and abstract contracts using functionality introduced in newer versions of Solidity can use caret range operators with higher path versions (e.g., `^0.8.24` when using transient storage opcodes). For interfaces, it should be considered to use the greater than or equal to (`>=`) range operator to ensure better compatibility with future versions of Solidity. + ### Interfaces Every contract MUST implement their corresponding interface that includes all externally callable functions, errors and events. From b0369b4d39a5fa168933c2d2c33f7620749c6b4f Mon Sep 17 00:00:00 2001 From: gretzke Date: Tue, 8 Jul 2025 01:47:43 +0200 Subject: [PATCH 09/17] add squash merge requirement --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be5e81b..33df3ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,6 +48,7 @@ In order for a PR to be merged, it must pass the following requirements: - Bug fixes must have a corresponding test that fails without the fix - The PR must be approved by at least one maintainer - The PR must be approved by 2+ maintainers if the PR is a new feature or > 100 LOC changed +- The PR must be squash merged into a single commit ## Code Practices From a203be3f35b104b57a9a881e6431aae14679b2d0 Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:20:39 +0200 Subject: [PATCH 10/17] Update gas snapshot section and reflect changes in template --- .forge-snapshots/Increment counter number.snap | 1 - .forge-snapshots/Set counter number.snap | 1 - .gitmodules | 3 --- .prettierignore | 1 + CONTRIBUTING.md | 3 ++- lib/forge-chronicles | 2 +- lib/forge-gas-snapshot | 1 - lib/forge-std | 2 +- snapshots/CounterTest_Deployed.json | 4 ++++ test/Counter.t.sol | 9 +++++---- 10 files changed, 14 insertions(+), 13 deletions(-) delete mode 100644 .forge-snapshots/Increment counter number.snap delete mode 100644 .forge-snapshots/Set counter number.snap delete mode 160000 lib/forge-gas-snapshot create mode 100644 snapshots/CounterTest_Deployed.json diff --git a/.forge-snapshots/Increment counter number.snap b/.forge-snapshots/Increment counter number.snap deleted file mode 100644 index 5f8239b..0000000 --- a/.forge-snapshots/Increment counter number.snap +++ /dev/null @@ -1 +0,0 @@ -26263 \ No newline at end of file diff --git a/.forge-snapshots/Set counter number.snap b/.forge-snapshots/Set counter number.snap deleted file mode 100644 index 1a947f3..0000000 --- a/.forge-snapshots/Set counter number.snap +++ /dev/null @@ -1 +0,0 @@ -26337 \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 7dc401b..eb431cd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "lib/forge-chronicles"] path = lib/forge-chronicles url = https://github.com/0xPolygon/forge-chronicles -[submodule "lib/forge-gas-snapshot"] - path = lib/forge-gas-snapshot - url = https://github.com/marktoda/forge-gas-snapshot diff --git a/.prettierignore b/.prettierignore index 45f4529..f646773 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,4 @@ cache/ docs/autogenerated *.sol deployments/ +snapshots/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 33df3ea..3fad35b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -147,7 +147,8 @@ When the contracts are compiled via IR, tests should be compiled without IR and ### Gas Metering -The [Forge Gas Snapshot](https://github.com/marktoda/forge-gas-snapshot) library is used to measure the gas cost of individual actions. Tests that measure gas should be annotated with `/// forge-config: default.isolate = true` and not be fuzzed to ensure that the gas snapshot is accurate and consistent for CI verification. All external functions should have a gas snapshot test, diverging paths within a function should have appropriate gas snapshot tests. +Gas for function calls should be metered using the built in `vm.snapshotGasLastCall` function in forge. To meter across multiple calls `vm.startSnapshotGas` and `vm.stopSnapshotGas` can be used. Tests that measure gas should be annotated with `/// forge-config: default.isolate = true` and not be fuzzed to ensure that the gas snapshot is accurate and consistent for CI verification. All external functions should have a gas snapshot test, diverging paths within a function should have appropriate gas snapshot tests. +For more information on gas metering see the [Forge cheatcodes reference](https://getfoundry.sh/reference/cheatcodes/gas-snapshots/#snapshotgas-cheatcodes). ## Deployment diff --git a/lib/forge-chronicles b/lib/forge-chronicles index c2be7a4..d1fb566 160000 --- a/lib/forge-chronicles +++ b/lib/forge-chronicles @@ -1 +1 @@ -Subproject commit c2be7a462d87b8e3a72f7e2b739cdf12807a71e4 +Subproject commit d1fb566915f23a01f08747264c56f8925f15751a diff --git a/lib/forge-gas-snapshot b/lib/forge-gas-snapshot deleted file mode 160000 index 9161f7c..0000000 --- a/lib/forge-gas-snapshot +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9161f7c0b6c6788a89081e2b3b9c67592b71e689 diff --git a/lib/forge-std b/lib/forge-std index 5475f85..60acb7a 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 5475f852e3f530d7e25dfb4596aa1f9baa8ffdfc +Subproject commit 60acb7aaadcce2d68e52986a0a66fe79f07d138f diff --git a/snapshots/CounterTest_Deployed.json b/snapshots/CounterTest_Deployed.json new file mode 100644 index 0000000..c88dfa7 --- /dev/null +++ b/snapshots/CounterTest_Deployed.json @@ -0,0 +1,4 @@ +{ + "Increment counter number": "26263", + "Set counter number": "26337" +} \ No newline at end of file diff --git a/test/Counter.t.sol b/test/Counter.t.sol index e23ed0d..cc06c84 100644 --- a/test/Counter.t.sol +++ b/test/Counter.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import {GasSnapshot} from 'forge-gas-snapshot/GasSnapshot.sol'; import 'forge-std/Test.sol'; import {CounterDeployer, ICounter} from './deployers/CounterDeployer.sol'; @@ -16,14 +15,15 @@ abstract contract Deployed is CounterDeployer { } } -contract CounterTest_Deployed is Deployed, GasSnapshot { +contract CounterTest_Deployed is Deployed { function test_IsInitialized() public view { assertEq(counter.number(), 10); } + /// forge-config: default.isolate = true function test_IncrementsNumber() public { counter.increment(); - snapLastCall('Increment counter number'); + vm.snapshotGasLastCall('Increment counter number'); assertEq(counter.number(), 11); } @@ -32,10 +32,11 @@ contract CounterTest_Deployed is Deployed, GasSnapshot { assertEq(counter.number(), x); } + /// forge-config: default.isolate = true function test_SetNumber_gas() public { uint256 x = 100; counter.setNumber(x); - snapLastCall('Set counter number'); + vm.snapshotGasLastCall('Set counter number'); } } From e8b2abd0bf5a719093264771149eabae24045645 Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:21:08 +0200 Subject: [PATCH 11/17] Revert "delete branching strategy" This reverts commit f6ad5577a8ecac40bb9aa113f42b8a5dce370505. --- CONTRIBUTING.md | 30 ++++++++++++++++++++++++++++++ docs/autogen/book.toml | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3fad35b..24578e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,12 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Install](#install) - [Pre-commit Hooks](#pre-commit-hooks) - [Requirements for merge](#requirements-for-merge) +- [Branching](#branching) + - [Main](#main) + - [Staging](#staging) + - [Dev](#dev) + - [Feature](#feature) + - [Fix](#fix) - [Code Practices](#code-practices) - [Code Style](#code-style) - [Solidity Versioning](#solidity-versioning) @@ -50,6 +56,30 @@ In order for a PR to be merged, it must pass the following requirements: - The PR must be approved by 2+ maintainers if the PR is a new feature or > 100 LOC changed - The PR must be squash merged into a single commit +## Branching + +This section outlines the branching strategy of this repo. + +### Main + +The main branch is supposed to reflect the deployed state on all networks. Any pull requests into this branch MUST come from the staging branch. + +### Staging + +The staging branch reflects new code complete deployments or upgrades containing fixes and/or features. Any pull requests into this branch MUST come from the dev branch. The staging branch is used for security audits and deployments. Once the deployment is complete and verified as well as deployment log files are generated, the branch can be merged into main. For more information on the deployment and log file generation check [here](#deployment). + +### Dev + +This is the active development branch. All pull requests into this branch MUST come from fix or feature branches. Upon code completion this branch is merged into staging for auditing and deployment. PRs into this branch should squash all commits into a single commit. + +### Feature + +Any new feature should be developed on a separate branch. The naming convention for these branches is `feat/*`. Once the feature is complete, a pull request into the dev branch can be created. + +### Fix + +Any bug fixes should be developed on a separate branch. The naming convention for these branches is `fix/*`. Once the fix is complete, a pull request into the dev branch can be created. + ## Code Practices ### Code Style diff --git a/docs/autogen/book.toml b/docs/autogen/book.toml index 6654d46..9ef6709 100644 --- a/docs/autogen/book.toml +++ b/docs/autogen/book.toml @@ -6,7 +6,6 @@ title = "" no-section-label = true additional-js = ["solidity.min.js"] additional-css = ["book.css"] -mathjax-support = true git-repository-url = "https://github.com/Uniswap/foundry-template" [output.html.fold] From 1c182ce69af69b01ebddc9c81f93de84fbef4d29 Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:30:26 +0200 Subject: [PATCH 12/17] Update branching strategy --- CONTRIBUTING.md | 30 +++++++++++------------------- docs/autogen/book.toml | 1 + 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24578e9..2e0c354 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,10 +7,8 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Requirements for merge](#requirements-for-merge) - [Branching](#branching) - [Main](#main) - - [Staging](#staging) - [Dev](#dev) - - [Feature](#feature) - - [Fix](#fix) + - [Audit](#audit) - [Code Practices](#code-practices) - [Code Style](#code-style) - [Solidity Versioning](#solidity-versioning) @@ -22,8 +20,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Gas Metering](#gas-metering) - [Deployment](#deployment) - [Deployment](#deployment-1) - - [Deployment Info Generation](#deployment-info-generation) -- [Releases](#releases) + - [Monorepo](#monorepo) ## Install @@ -62,23 +59,15 @@ This section outlines the branching strategy of this repo. ### Main -The main branch is supposed to reflect the deployed state on all networks. Any pull requests into this branch MUST come from the staging branch. - -### Staging - -The staging branch reflects new code complete deployments or upgrades containing fixes and/or features. Any pull requests into this branch MUST come from the dev branch. The staging branch is used for security audits and deployments. Once the deployment is complete and verified as well as deployment log files are generated, the branch can be merged into main. For more information on the deployment and log file generation check [here](#deployment). +The main branch is supposed to reflect the deployed state on all networks. Only audited code should be merged into main. ### Dev -This is the active development branch. All pull requests into this branch MUST come from fix or feature branches. Upon code completion this branch is merged into staging for auditing and deployment. PRs into this branch should squash all commits into a single commit. - -### Feature +This is the active development branch. Upon code completion this branch is frozen on an audit branch. PRs into this branch should squash all commits into a single commit. In case of multiple parallel development efforts, each project should have its own dev branch with the naming convention `dev/` to ensure work in progress is isolated and does not end up on the main branch. -Any new feature should be developed on a separate branch. The naming convention for these branches is `feat/*`. Once the feature is complete, a pull request into the dev branch can be created. +### Audit -### Fix - -Any bug fixes should be developed on a separate branch. The naming convention for these branches is `fix/*`. Once the fix is complete, a pull request into the dev branch can be created. +Before an audit, the code should be frozen on a branch dedicated to the audit with the naming convention `audit/`. Each fix in response to an audit finding should be developed on its own branch. The naming convention for these branches is `audit//`. The PR title should include the provider and the issue number at minimum. Sometimes it is desirable to have all of the fixes in a single PR for review. In this case, each fix PR should be included via the `merge` strategy, and the combined PR can be merged into the dev branch via `merge` to preserve the order of the fix commits. ## Code Practices @@ -182,14 +171,17 @@ For more information on gas metering see the [Forge cheatcodes reference](https: ## Deployment -After deployments are executed a script is provided that extracts deployment information from the `run-latest.json` file within the `broadcast` directory generated while the forge script runs. From this information a JSON and markdown file is generated using the [Forge Chronicles](https://github.com/0xPolygon/forge-chronicles) library containing various information about the deployment itself as well as past deployments. +After deployments are executed a script is provided that extracts deployment information from the `run-latest.json` file within the `broadcast` directory generated while the forge script runs. From this information a JSON and markdown file is generated using the [Forge Chronicles](https://github.com/uniswap/forge-chronicles) library containing various information about the deployment itself as well as past deployments. ### Deployment To deploy the contracts, provide the `--broadcast` flag to the forge script command. Should the etherscan verification time out, it can be picked up again by replacing the `--broadcast` flag with `--resume`. -Deploy the contracts to one of the predefined networks by providing the according key with the `--rpc-url` flag. Most of the predefined networks require the `INFURA_KEY` environment variable to be set in the `.env` file. Including the `--verify` flag will verify deployed contracts on Etherscan. Define the appropriate environment variable for the Etherscan api key in the `.env` file. ```shell forge script script/Deploy.s.sol --broadcast --rpc-url --verify ``` + +### Monorepo + +Alternatively, contracts should be integrated into the [Smart Contract Monorepo](https://github.com/uniswap/contracts) to be deployed via the deployer cli tool. diff --git a/docs/autogen/book.toml b/docs/autogen/book.toml index 9ef6709..6654d46 100644 --- a/docs/autogen/book.toml +++ b/docs/autogen/book.toml @@ -6,6 +6,7 @@ title = "" no-section-label = true additional-js = ["solidity.min.js"] additional-css = ["book.css"] +mathjax-support = true git-repository-url = "https://github.com/Uniswap/foundry-template" [output.html.fold] From 95e1fb8336690e291832a23070150167237dcfc3 Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:37:01 +0200 Subject: [PATCH 13/17] Add Dependency Management section --- .gitmodules | 3 +++ CONTRIBUTING.md | 29 +++++++++++++++++++++++++++++ lib/briefcase | 1 + 3 files changed, 33 insertions(+) create mode 160000 lib/briefcase diff --git a/.gitmodules b/.gitmodules index eb431cd..9183682 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/forge-chronicles"] path = lib/forge-chronicles url = https://github.com/0xPolygon/forge-chronicles +[submodule "lib/briefcase"] + path = lib/briefcase + url = https://github.com/Uniswap/briefcase diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e0c354..7b7e933 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,6 +21,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Deployment](#deployment) - [Deployment](#deployment-1) - [Monorepo](#monorepo) +- [Dependency Management](#dependency-management) ## Install @@ -185,3 +186,31 @@ forge script script/Deploy.s.sol --broadcast --rpc-url --verify ### Monorepo Alternatively, contracts should be integrated into the [Smart Contract Monorepo](https://github.com/uniswap/contracts) to be deployed via the deployer cli tool. + +## Dependency Management + +The preferred way to manage dependencies is using [`forge install`](https://book.getfoundry.sh/forge/dependencies). This ensures that your project uses the correct versions and structure for all external libraries. + +However, in cases where there is a Solidity version mismatch between your project and a dependency, it may be required to include the compiled bytecode directly in a utility contract. This approach allows to deploy the dependency using the correct bytecode, regardless of source compatibility. This may be especially helpful for integration testing. + +First, it should be checked if the deployer is already part of [Briefcase](https://github.com/Uniswap/briefcase/tree/main/src/deployers). If so, import the deployer from here. + +Otherwise, a custom deploy contract should be created. Below is an example of how to deploy a contract using hardcoded bytecode and the `CREATE2` opcode. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; +contract BytecodeDeployer { + /// @dev Deploys a contract using CREATE2 with the provided bytecode and salt. + /// @param bytecode The contract bytecode to deploy. + /// @param salt The salt to use for CREATE2. + /// @return addr The address of the deployed contract. + function deploy(bytes memory bytecode, bytes32 salt) public returns (address addr) { + require(bytecode.length != 0, "Bytecode is empty"); + assembly { + addr := create2(bytecode, salt) + if iszero(extcodesize(addr)) { revert(0, 0) } + } + } +} +``` diff --git a/lib/briefcase b/lib/briefcase new file mode 160000 index 0000000..2b00819 --- /dev/null +++ b/lib/briefcase @@ -0,0 +1 @@ +Subproject commit 2b00819e5694c075a5437a9a0cde109fac0e6578 From 67fbf0c2d3b46592e171ca45ff2a6d2922cd638e Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:41:56 +0200 Subject: [PATCH 14/17] Add release section --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b7e933..4b7a867 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,6 +22,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Deployment](#deployment-1) - [Monorepo](#monorepo) - [Dependency Management](#dependency-management) +- [Releases](#releases) ## Install @@ -214,3 +215,7 @@ contract BytecodeDeployer { } } ``` + +## Releases + +Every deployment and changes made to contracts after deployment should be accompanied by a tag and release on GitHub. From 50966bbb1466fd2bb05e41f6a4fbdb91863bc5d0 Mon Sep 17 00:00:00 2001 From: gretzke Date: Wed, 9 Jul 2025 01:43:36 +0200 Subject: [PATCH 15/17] clarify single line natspec comment --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b7a867..357e79c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -148,7 +148,7 @@ Every contract MUST implement their corresponding interface that includes all ex ### NatSpec & Comments -Interfaces should be the entrypoint for all contracts. When exploring the a contract within the repository, the interface MUST contain all relevant information to understand the functionality of the contract in the form of NatSpec comments. This includes all externally callable functions, errors and events. The NatSpec documentation MUST be added to the functions, errors and events within the interface. This allows a reader to understand the functionality of a function before moving on to the implementation. The implementing functions MUST point to the NatSpec documentation in the interface using `@inheritdoc`. Internal and private functions shouldn't have NatSpec documentation except for `@dev` comments, whenever more context is needed. Additional comments within a function should only be used to give more context to more complex operations, otherwise the code should be kept readable and self-explanatory. NatSpec comments should be written with a triple slash (`///`) to ensure compact documentation. +Interfaces should be the entrypoint for all contracts. When exploring the a contract within the repository, the interface MUST contain all relevant information to understand the functionality of the contract in the form of NatSpec comments. This includes all externally callable functions, errors and events. The NatSpec documentation MUST be added to the functions, errors and events within the interface. This allows a reader to understand the functionality of a function before moving on to the implementation. The implementing functions MUST point to the NatSpec documentation in the interface using `@inheritdoc`. Internal and private functions shouldn't have NatSpec documentation except for `@dev` comments, whenever more context is needed. Additional comments within a function should only be used to give more context to more complex operations, otherwise the code should be kept readable and self-explanatory. Single line NatSpec comments should use a triple slash (`///`) to ensure compact documentation. ## Testing From 38ed59820aa3cbf20cb0977a09ce6a2735dcd942 Mon Sep 17 00:00:00 2001 From: gretzke Date: Thu, 10 Jul 2025 00:58:38 +0200 Subject: [PATCH 16/17] updated branching strategy --- CONTRIBUTING.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 357e79c..4cb94a9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [Branching](#branching) - [Main](#main) - [Dev](#dev) + - [Feature](#feature) - [Audit](#audit) - [Code Practices](#code-practices) - [Code Style](#code-style) @@ -53,7 +54,6 @@ In order for a PR to be merged, it must pass the following requirements: - Bug fixes must have a corresponding test that fails without the fix - The PR must be approved by at least one maintainer - The PR must be approved by 2+ maintainers if the PR is a new feature or > 100 LOC changed -- The PR must be squash merged into a single commit ## Branching @@ -61,12 +61,16 @@ This section outlines the branching strategy of this repo. ### Main -The main branch is supposed to reflect the deployed state on all networks. Only audited code should be merged into main. +The main branch is supposed to reflect the deployed state on all networks. Only audited code should be merged into main. Squashed commits from dev or feature branches should be merged into the main branch using a regular merge strategy. ### Dev This is the active development branch. Upon code completion this branch is frozen on an audit branch. PRs into this branch should squash all commits into a single commit. In case of multiple parallel development efforts, each project should have its own dev branch with the naming convention `dev/` to ensure work in progress is isolated and does not end up on the main branch. +### Feature + +Feature branches should be owned by one responsible developer. The dev branch should be the target of the feature branch. In pre-audit and pre-deployment repositories feature branches may be merged into the main branch directly. Generally, feature branches should be squashed into a single commit before merging. + ### Audit Before an audit, the code should be frozen on a branch dedicated to the audit with the naming convention `audit/`. Each fix in response to an audit finding should be developed on its own branch. The naming convention for these branches is `audit//`. The PR title should include the provider and the issue number at minimum. Sometimes it is desirable to have all of the fixes in a single PR for review. In this case, each fix PR should be included via the `merge` strategy, and the combined PR can be merged into the dev branch via `merge` to preserve the order of the fix commits. From 1a11c6ff7e8f1c74d86dbeda3c8692b1ad6719b0 Mon Sep 17 00:00:00 2001 From: gretzke Date: Thu, 10 Jul 2025 15:15:13 +0200 Subject: [PATCH 17/17] Add bytecode hash --- CONTRIBUTING.md | 13 ++++--------- foundry.toml | 1 + 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4cb94a9..99f19cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ For the latest version of this document, see [here](https://github.com/Uniswap/f - [IR Compilation](#ir-compilation) - [Gas Metering](#gas-metering) - [Deployment](#deployment) - - [Deployment](#deployment-1) + - [Bytecode Hash](#bytecode-hash) - [Monorepo](#monorepo) - [Dependency Management](#dependency-management) - [Releases](#releases) @@ -179,18 +179,13 @@ For more information on gas metering see the [Forge cheatcodes reference](https: After deployments are executed a script is provided that extracts deployment information from the `run-latest.json` file within the `broadcast` directory generated while the forge script runs. From this information a JSON and markdown file is generated using the [Forge Chronicles](https://github.com/uniswap/forge-chronicles) library containing various information about the deployment itself as well as past deployments. -### Deployment +### Bytecode Hash -To deploy the contracts, provide the `--broadcast` flag to the forge script command. Should the etherscan verification time out, it can be picked up again by replacing the `--broadcast` flag with `--resume`. -Including the `--verify` flag will verify deployed contracts on Etherscan. Define the appropriate environment variable for the Etherscan api key in the `.env` file. - -```shell -forge script script/Deploy.s.sol --broadcast --rpc-url --verify -``` +Bytecode hash MUST be set to `none` in the `foundry.toml` file to ensure that the bytecode is consistent. ### Monorepo -Alternatively, contracts should be integrated into the [Smart Contract Monorepo](https://github.com/uniswap/contracts) to be deployed via the deployer cli tool. +Contracts should be integrated into the [Smart Contract Monorepo](https://github.com/uniswap/contracts) to be deployed via the deployer cli tool. ## Dependency Management diff --git a/foundry.toml b/foundry.toml index 391d308..43c57a1 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,6 +6,7 @@ optimizer = true optimizer_runs = 999999 via_ir = true solc = "0.8.26" +bytecode_hash = "none" verbosity = 2 ffi = true fs_permissions = [