Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CLI Foundry Template #854

Closed
wants to merge 82 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
9a10b39
Semaphore identity example code bug fix
weipooppys93030 Aug 12, 2024
68df0d9
Receive suggestion for consistency
weipooppys93030 Aug 12, 2024
845e49c
chore: forge init
timou0911 Sep 5, 2024
7db237f
forge install: forge-std
timou0911 Sep 5, 2024
3924f5f
Foundry CLI First Draft
timou0911 Sep 5, 2024
c507097
Merge branch 'new_branch' of https://github.com/csiejimmyliu/semaphor…
csiejimmyliu Sep 5, 2024
8e73c32
modules
csiejimmyliu Sep 5, 2024
db8db8e
forge install: semaphore
csiejimmyliu Sep 5, 2024
1455706
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
88b7b46
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
29228d9
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
a062c6a
modules
csiejimmyliu Sep 5, 2024
0ec856e
forge install: semaphore
csiejimmyliu Sep 5, 2024
de881bb
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
967fade
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
4754073
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
caf1e7a
modules
csiejimmyliu Sep 5, 2024
3193f7d
forge install: semaphore
csiejimmyliu Sep 5, 2024
4ac8c36
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
7fba0cf
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
a4e5fe9
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
92dae03
modules
csiejimmyliu Sep 5, 2024
1f1214c
forge install: semaphore
csiejimmyliu Sep 5, 2024
4a26225
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
1eba2a9
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
d553272
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
8197522
modules
csiejimmyliu Sep 5, 2024
18446f8
forge install: semaphore
csiejimmyliu Sep 5, 2024
eb9b2c2
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
ba33b5d
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
d1b755e
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
bdfe270
modules
csiejimmyliu Sep 5, 2024
c13fef9
forge install: semaphore
csiejimmyliu Sep 5, 2024
fa7cf9a
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
a72abc9
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
997264f
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
7601e50
forge install: forge-std
csiejimmyliu Sep 5, 2024
2473ad8
modules
csiejimmyliu Sep 5, 2024
df86f35
forge install: semaphore
csiejimmyliu Sep 5, 2024
d6b8b48
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
b22b15d
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
e179470
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
ceed128
modules
csiejimmyliu Sep 5, 2024
0f05f4f
forge install: semaphore
csiejimmyliu Sep 5, 2024
6266bb5
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
6d9843c
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
2f874b6
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
bb40b95
forge install: forge-std
csiejimmyliu Sep 5, 2024
d4e83b5
modules
csiejimmyliu Sep 5, 2024
ab8d1f6
forge install: semaphore
csiejimmyliu Sep 5, 2024
1a561fb
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
5de7d1b
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
589b080
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
8006eda
forge install: forge-std
csiejimmyliu Sep 5, 2024
cf5fedc
modules
csiejimmyliu Sep 5, 2024
a12b1b1
forge install: semaphore
csiejimmyliu Sep 5, 2024
0c88ced
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
ba78da7
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
081bce4
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
877ad59
modules
csiejimmyliu Sep 5, 2024
8e790ce
forge install: semaphore
csiejimmyliu Sep 5, 2024
c28befb
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
5465816
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
5bc6eac
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
b83d5c2
forge install: forge-std
csiejimmyliu Sep 5, 2024
5a53df7
modules
csiejimmyliu Sep 5, 2024
f13c7e5
forge install: semaphore
csiejimmyliu Sep 5, 2024
e064f4e
forge install: zk-kit.solidity
csiejimmyliu Sep 5, 2024
d338f27
forge install: poseidon-solidity
csiejimmyliu Sep 5, 2024
826b659
forge install: openzeppelin-contracts
csiejimmyliu Sep 5, 2024
5bc93e7
forge install: forge-std
csiejimmyliu Sep 5, 2024
76afd09
change test name
csiejimmyliu Sep 5, 2024
56ae53b
modify declaration of semaphore and verifier
csiejimmyliu Sep 5, 2024
673b801
Modify Test Function Name
timou0911 Sep 7, 2024
46b3c14
Add Test Chain Target
timou0911 Sep 7, 2024
721f26c
forge std install
csiejimmyliu Sep 7, 2024
4832baa
refactor(cli-template-contracts-foundry): change default Anvil addres…
timou0911 Sep 9, 2024
22ea215
chore(cli-template-contracts-foundry): add comments
timou0911 Sep 9, 2024
52eea1b
refactor(cli-template-contracts-foundry): add Semaphore & SemaphoreVe…
timou0911 Sep 9, 2024
f02da82
chore(cli-template-contracts-foundry): add forge coverage for Makefile
timou0911 Sep 9, 2024
5373034
chore(cli-template-contracts-foundry): add env.example
timou0911 Sep 9, 2024
072b11f
docs(cli-template-contracts-foundry): add command instructions
timou0911 Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[submodule "packages/cli-template-contracts-foundry/lib/forge-std"]
path = packages/cli-template-contracts-foundry/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "packages/cli-template-contracts-foundry/lib/semaphore"]
path = packages/cli-template-contracts-foundry/lib/semaphore
url = https://github.com/semaphore-protocol/semaphore
[submodule "packages/cli-template-contracts-foundry/lib/zk-kit.solidity"]
path = packages/cli-template-contracts-foundry/lib/zk-kit.solidity
url = https://github.com/privacy-scaling-explorations/zk-kit.solidity
[submodule "packages/cli-template-contracts-foundry/lib/poseidon-solidity"]
path = packages/cli-template-contracts-foundry/lib/poseidon-solidity
url = https://github.com/chancehudson/poseidon-solidity
[submodule "packages/cli-template-contracts-foundry/lib/openzeppelin-contracts"]
path = packages/cli-template-contracts-foundry/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
4 changes: 4 additions & 0 deletions packages/cli-template-contracts-foundry/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SEPOLIA_RPC_URL=
SEPOLIA_API_URL=
ETHERSCAN_API_KEY=
PRIVATE_KEY=
14 changes: 14 additions & 0 deletions packages/cli-template-contracts-foundry/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
Empty file.
48 changes: 48 additions & 0 deletions packages/cli-template-contracts-foundry/Makefile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally love Makefile as a task runner.
But I am wondering if it is appropriate for this repo.
This repo is very "node ecosystem" oriented. So we run tasks with yarn.
On one side I agree it may not make much sense to use yarn as a task runner for a template that does not include any js,ts files, making make a good choice.
One the other side, for the sake of consistency maybe we should stick to yarn: meaning all these make tasks belong rather in package.json scripts. And eventually we need a package.json in order to publish the template as an npm package... so...

What do you think @vplasencia @cedoor ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree! As soon as we have 1 non-NPM package only we should make it a NPM package. If there are many other non-NPM packages we can think of a system to download templates that is more language-agnostic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Regarding if it's better to use Makefile or yarn, I think it depends on what developers prefer when using Foundry. If most devs prefer to use Makefile, we should provide the Foundry template with Makefile and if they prefer yarn (npm, pnpm) we should provide the Foundry template with yarn. If there are no strong opinions on that we could decide one.

If we have to decide one, I see pros and cons. I think for just contracts, Makefile could be lighter and easier to add but for bigger projects yarn (npm, pnpm) could be better.

I have seen projects using both, so another alternative to discuss could be if it's better to add both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about having Makefile as a task runner and a package.json to make it compatible/downloadable with our CLI?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also add a package.json to download the template and then remove it after it's downloaded, the same way we create the yarn.lock file but removing a file instead of creating it.

Or if we keep the package.json and add the scripts so that people decide the one they prefer and remove the Makefile or the package.json and yarn.lock files.

What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to prefer the first option.

@sripwoud ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes let's go with the option of keeping the Makefile and removing the package.json after it having been downloaded. (That's was the 1st option right?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timou0911 @sripwoud Is this PR ready to be merged?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I was busy in the past few weeks. I will start handling it next week.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem!

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
-include .env

DEFAULT_ANVIL_KEY := 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
DEFAULT_ANVIL_ADDRESS := 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
DEFAULT_RPC_URL := http://localhost:8545

.PHONY: all test clean

all: clean remove install build

# Clean the repo
clean :; forge clean

# Remove modules
remove :; rm -rf .gitmodules && rm -rf .git/modules/* && rm -rf lib && touch .gitmodules && git add . && git commit -m "modules"

install :; forge install semaphore-protocol/semaphore privacy-scaling-explorations/zk-kit.solidity chancehudson/poseidon-solidity OpenZeppelin/openzeppelin-contracts foundry-rs/forge-std

install-no-git :; forge install --no-git semaphore-protocol/semaphore privacy-scaling-explorations/zk-kit.solidity chancehudson/poseidon-solidity OpenZeppelin/openzeppelin-contracts foundry-rs/forge-std

# Update Dependencies
update :; forge update

build :; forge build

test :; forge test -vvv

gas-report :; forge test --gas-report

coverage :; forge coverage

snapshot :; forge snapshot

format :; forge fmt

slither :; slither ./src

#format :; prettier --write src/**/*.sol && prettier --write src/*.sol

# solhint should be installed globally
lint :; solhint src/**/*.sol && solhint src/*.sol

# use the "@" to hide the command from your shell
deploy :; @forge script script/DeployFeedback.s.sol:DeployFeedback --rpc-url $(DEFAULT_RPC_URL) --private-key $(DEFAULT_ANVIL_KEY) --broadcast -vvvvv

deploy-sepolia :; @forge script script/DeployFeedback.s.sol:DeployFeedback --rpc-url $(SEPOLIA_RPC_URL) --private-key $(PRIVATE_KEY) --broadcast --etherscan-api-key $(ETHERSCAN_API_KEY) -vvvvv

deploy-sepolia-verify :; @forge script script/DeployFeedback.s.sol:DeployFeedback --rpc-url $(SEPOLIA_RPC_URL) --private-key $(PRIVATE_KEY) --broadcast --verify --etherscan-api-key $(ETHERSCAN_API_KEY) -vvvvv
89 changes: 89 additions & 0 deletions packages/cli-template-contracts-foundry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Semaphore Foundry Template

This project demonstrates a basic Semaphore use case. It comes with a sample contract, a test for that contract and a sample script that deploys that contract.

## Install  

### Install dependencies

```bash
make install
```

## Usage

### Compile contracts

```bash
make build
```

### Test

```bash
make test
```

You can also generate a test coverage report:

```bash
make coverage
```

Or a test gas report:

```bash  
make gas-report
```

### Deploy contracts

1. Copy the `.env.example` file as `.env`.

```bash
cp .env.example .env
```

2. Add your environment variables.

> [!NOTE]
> You should at least set a valid Ethereum URL (e.g. Infura) and a private key with some ethers.

3. And deploy your contract.

```bash
make deploy
```

4. You can also deploy your contract in Sepolia test chain.

```bash
make deploy-sepolia
```

```bash
make deploy-sepolia-verify
```

> [!NOTE]
> Check the Semaphore contract addresses [here](https://docs.semaphore.pse.dev/deployed-contracts).

### Code quality and formatting

Run [ESLint](https://eslint.org/) and [solhint](https://github.com/protofire/solhint) to analyze the code and catch bugs:

```bash
yarn lint
```

Run [Prettier](https://prettier.io/) to check formatting rules:

```bash
yarn prettier
```

Or to automatically format the code:

```bash
yarn prettier:write
```
13 changes: 13 additions & 0 deletions packages/cli-template-contracts-foundry/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

remappings = [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@zk-kit/lean-imt.sol=lib/zk-kit.solidity/packages/lean-imt/contracts/",
"@semaphore/contracts/=lib/semaphore/packages/contracts/",
"poseidon-solidity/=lib/poseidon-solidity/contracts/"
]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions packages/cli-template-contracts-foundry/lib/forge-std
Submodule forge-std added at 1714be
Submodule poseidon-solidity added at 8205c9
1 change: 1 addition & 0 deletions packages/cli-template-contracts-foundry/lib/semaphore
Submodule semaphore added at 7d4831
Submodule zk-kit.solidity added at a4e713
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {Feedback} from "../src/Feedback.sol";
import {Semaphore} from "@semaphore/contracts/contracts/Semaphore.sol";
import {SemaphoreVerifier} from "@semaphore/contracts/contracts/base/SemaphoreVerifier.sol";
import {ISemaphoreVerifier} from "@semaphore/contracts/contracts/interfaces/ISemaphoreVerifier.sol";
import "forge-std/Script.sol";

contract DeployFeedback is Script {
function run() external returns (address, address) {

address semaphoreVerifierAddress;
address semaphoreAddress;

if (block.chainid == 11155111) {
semaphoreVerifierAddress = 0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043;
semaphoreAddress = 0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f;
}

vm.startBroadcast();

if (semaphoreAddress == address(0)) {
// Deploy SemaphoreVerifier for Semaphore
SemaphoreVerifier semaphoreVerifier = new SemaphoreVerifier();
semaphoreVerifierAddress = address(semaphoreVerifier);
ISemaphoreVerifier IsemaphoreVerifier = ISemaphoreVerifier(address(semaphoreVerifier));
// Deploy Semaphore for Feedback
Semaphore semaphore = new Semaphore(IsemaphoreVerifier);
semaphoreAddress = address(semaphore);
}

// Deploy Feedback
Feedback feedback = new Feedback(semaphoreAddress);

vm.stopBroadcast();

console.log("Feedback contract has been deployed to:", address(feedback));

return (address(feedback), semaphoreAddress);
}
}
39 changes: 39 additions & 0 deletions packages/cli-template-contracts-foundry/src/Feedback.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {ISemaphore} from "@semaphore/contracts/contracts/interfaces/ISemaphore.sol";

contract Feedback {
ISemaphore public semaphore;

uint256 public groupId;

constructor(address semaphoreAddress) {
semaphore = ISemaphore(semaphoreAddress);

groupId = semaphore.createGroup();
}

function joinGroup(uint256 identityCommitment) external {
semaphore.addMember(groupId, identityCommitment);
}

function sendFeedback(
uint256 merkleTreeDepth,
uint256 merkleTreeRoot,
uint256 nullifier,
uint256 feedback,
uint256[8] calldata points
) external {
ISemaphore.SemaphoreProof memory proof = ISemaphore.SemaphoreProof(
merkleTreeDepth,
merkleTreeRoot,
nullifier,
feedback,
groupId,
points
);

semaphore.validateProof(groupId, proof);
}
}
62 changes: 62 additions & 0 deletions packages/cli-template-contracts-foundry/test/TestFeedback.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {Feedback} from "../src/Feedback.sol";
import {DeployFeedback} from "../script/DeployFeedback.s.sol";
import {ISemaphore} from "@semaphore/contracts/contracts/interfaces/ISemaphore.sol";
import "forge-std/Test.sol";
import "forge-std/Vm.sol";
import "forge-std/StdAssertions.sol";

contract TestFeedback is Test {
event MemberAdded(uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 merkleTreeRoot);

Feedback feedback;
ISemaphore semaphore;

function setUp() external {
DeployFeedback deployFeedback = new DeployFeedback();
(address feedbackAddress, address semaphoreAddress) = deployFeedback.run();
feedback = Feedback(feedbackAddress);
semaphore = ISemaphore(semaphoreAddress);
}

function testGroupCanBeSuccessfullyCreatedInConstructor() public view {
uint256 groupCount = semaphore.groupCounter();
assertEq(groupCount, 1);
}

function testJoinGroup() public {
// The commitment below is generated with private key of the first account in Anvil
uint256 identityCommitment = 15072455385723004728391568434269917452175057560864330595979104241296826134229;

vm.expectEmit();
emit MemberAdded(0, 0, identityCommitment, identityCommitment);

feedback.joinGroup(identityCommitment);
}

function testSendFeedback() public {
// The commitment below is generated with private key of the first account in Anvil
uint256 identityCommitment = 15072455385723004728391568434269917452175057560864330595979104241296826134229;

// proof
uint256 merkleTreeDepth = 1;
uint256 merkleTreeRoot = 15072455385723004728391568434269917452175057560864330595979104241296826134229;
uint256 nullifier = 19686122779422310562166284157356225273555811832250923548604308577995736533741;
uint256 _feedback = 10;
uint256[8] memory points = [
12048312860461559338883155239253399933546666729690013703471566999549175452467,
21840091385609522690103928000869734241136862303146585471149748945500784854265,
10054166788431277732934266072748176286083365382773741957806739135617485223542,
9116054769380232069869558420495933708797671282085269461846220481242548419978,
6948551756635965397908570768367265912884504926499199123083878377204200654789,
2245690128809758381379719477871572712156305432595569015554741897717367802975,
5611601698470220983640634359607737788561497874240905720723835997666161640377,
10003362076211645361201917446734540672642362716488164733173444779942043660944
];

feedback.joinGroup(identityCommitment);
feedback.sendFeedback(merkleTreeDepth, merkleTreeRoot, nullifier, _feedback, points);
}
}
Loading