Thanks for your interest in improving the Farcaster Contracts!
No contribution is too small and we welcome to your help. There's always something to work on, no matter how experienced you are. If you're looking for ideas, start with the good first issue or help wanted sections in the issues. You can help make Farcaster better by:
- Opening issues or adding details to existing issues
- Fixing bugs in the code
- Making tests or the ci builds faster
- Improving the documentation
- Keeping dependencies up-to-date
- Proposing and implementing new features
Before you get down to coding, take a minute to consider this:
- If your proposal modifies the farcaster protocol, open an issue there first.
- If your proposal is a non-trivial change, consider opening an issue first to get buy-in.
- If your issue is a small bugfix or improvement, you can simply make the changes and open the PR.
Install the following packages globally before you get started:
- Foundry - smart contract toolchain
- Slither - smart contract static analysis tool
- Rust/Cargo - for git pre-commit hooks
Once they are installed globally, run cargo build
, forge build
, forge test
and slither .
to verify that they
are working. Expect the slither command to print several warnings which are false positives or non-issues.
All commits must be signed with a GPG key, which is a second factor that proves that your commits came from a device in your control. It protects against the case where your GitHub account gets compromised. To get started:
- Generate new GPG Keys. We recommend using GPG Suite on OSX.
- Use
gpg-agent
to remember your password locally
vi ~/.gnupg/gpg-agent.conf
default-cache-ttl 100000000
max-cache-ttl 100000000
- Upload your GPG Keys to your Github Account
- Configure Git to use your keys when signing.
- Configure Git to always sign commits by running
git config --global commit.gpgsign true
- Commit all changes with your usual git commands and you should see a
Verified
badge near your commits
yarn format
uses forge fmt to find and auto-correct formatting issues.yarn format:check
performs the same checks, but alerts on errors and does not fix them.
Code follows the Solidity style guide and documentation follows Ethereum Natspec unless otherwise specified. If you use VS Code, you can lint-on-save by installing the Solidity and ESLint extensions.
Anvil can be used to run a local instance of a blockchain which is useful for rapid testing and prototyping.
- Run
anvil
in a shell to start the local blockchain. - Copy one of the private keys that anvil outputs to pass in as an arg in the next step.
- Run
forge script script/IdRegistry.s.sol:IdRegistryScript --private-key <private_key> --broadcast --verify --fork-url http://127.0.0.1:8545
to deploy the contract
A node provider like Alchemy, Infura or Coinbase can be used to deploy the contract to the Goerli network. First,
create a .env
file with the following secrets:
GOERLI_RPC_URL
- get this from your node provider (alchemy/infura)GOERLI_PRIVATE_KEY
- export this from a non-critical metamask wallet that has some goerli ethETHERSCAN_KEY
- get this from the etherscan api
-
Load the environment variables into your shell with
source .env
-
Run
forge script script/IdRegistry.s.sol:IdRegistryScript --rpc-url $GOERLI_RPC_URL --private-key $GOERLI_PRIVATE_KEY --broadcast --verify --etherscan-api-key $ETHERSCAN_KEY -vvvv
This can take several seconds and generates .json outputs with deployment details. Do not commit these changes unless you are making a new public deployment. Passing in the Etherscan params to verify the contract makes your code publicly available on the contract and allows calling the contract through the UI.
If you see a solc dyld error like the one below and you are on an M1, follow the steps here: foundry-rs/foundry#2712
Solc Error: dyld[35225]: Library not loaded: '/opt/homebrew/opt/z3/lib/libz3.dylib'
Referenced from: '/Users/<yourusername>/.svm/0.8.18/solc-0.8.18'
Reason: tried: '/opt/homebrew/opt/z3/lib/libz3.dylib' (no such file), '/usr/local/lib/libz3.dylib' (no such file), '/usr/lib/libz3.dylib' (no such file)
There's an intermittent issue with Etherscan where verification of the contract fails during deployment. Redeploying the contract later seems to resolve this.
Forge's gas reporting tool can be inaccurate when run across our entire test suite. Gas estimates can be lower than
expected because tests cover failure cases that terminate early, or higher than expected because the first test run
always causes storage initialization. A more robust way is to write a special suite of tests that mimic real-world
usage of contracts and estimate gas on those calls only. Our gas estimation suite can be invoked with
forge test --match-contract GasUsage --gas-report
.
When proposing a change, make sure that you've followed all of these steps before you ask for a review.
All changes that involve features or bugfixes should have supporting Foundry tests. The tests should:
- Live in the
test/
folder - Fuzz all possible states including user inputs and time warping
- Cover all code paths and states that were added
- Be written as unit tests, and with supporting feature tests if necessary
All changes should have supporting documentation that makes reviewing and understand the code easy. You should:
- Update high-level changes in the contract docs.
- Write or update Natspec comments for any relevant functions, variables, constants, events and params.
- Add comments explaining the 'why' when code is not obvious.
- Add a
Safety: ..
comment explaining every use ofunsafe
. - Add a comment explaining every usage of assembly or fancy math.
- Add a comment explaining every gas optimization along with how much gas it saves.
You should walk through the following steps locally before pushing a PR for review:
- Check gas usage by running
forge test -vvv --match-contract Gas
- Check the coverage with
forge coverage
- Look for issues with slither by running
slither .
- Walk through the solcurity checklist
If your changes increase gas usage, reduce coverage, introduce new slither issues or violate any solcurity rules you must document the rationale clearly in the PR and in the code if appropriate.
All submissions must be opened as a Pull Request with a full CI run completed. Assign PR's to @v / varunsrin for review. When creating your PR:
- The PR titles must follow the Conventional Commits spec
- Commit titles should follow the Conventional Commits spec
As an example, a good PR title would look like this:
fix(IdRegistry): idCounter should be incremented by 1 before transferring the id
While a good commit message might look like this:
fix(IdRegistry): idCounter should be incremented by 1 before transferring the id
idCounter was being incremented after the transfer id call which increases gas utilization
in some conditions