Skip to content

Commit

Permalink
feat(contracts): add title (#20)
Browse files Browse the repository at this point in the history
* feat(contracts): add title

* chore: lint

* chore: deploy `YesNoFeedback` on `arbitrum-sepolia`
  • Loading branch information
sripwoud authored Oct 15, 2024
1 parent 124effa commit 733e52e
Show file tree
Hide file tree
Showing 10 changed files with 32 additions and 33 deletions.
2 changes: 1 addition & 1 deletion apps/client/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const clientConfig: SharedConfigI & ClientConfigI = {
description: 'Anonymous survey and feedback platform',
},
contracts: {
[Contract.YesNoFeedback]: { [arbitrumSepolia.id]: '0x92844a251EC890141F6617c9c2ef7eEb26a81ad8' as HexString },
[Contract.YesNoFeedback]: { [arbitrumSepolia.id]: '0x4308bfd6c6cd829b6d342c90b43bef46700cec8d' as HexString },
[Contract.Semaphore]: { [arbitrumSepolia.id]: '0x1e0d7FF1610e480fC93BdEC510811ea2Ba6d7c2f' as HexString },
},
serverUrl,
Expand Down
2 changes: 1 addition & 1 deletion contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

| name | network | address |
| -------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [YesNoFeedback](src/YesNoFeedback.sol) | arbitrum-sepolia | [0x92844a251EC890141F6617c9c2ef7eEb26a81ad8](https://sepolia.arbiscan.io/address/0x92844a251EC890141F6617c9c2ef7eEb26a81ad8#code) |
| [YesNoFeedback](src/YesNoFeedback.sol) | arbitrum-sepolia | [0x4308bfd6c6cd829b6d342c90b43bef46700cec8d](https://sepolia.arbiscan.io/address/0x4308bfd6c6cd829b6d342c90b43bef46700cec8d#code) |
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@semaphore-protocol/contracts": "^4.3.0"
},
"scripts": {
"deploy.arb1sepolia.yesno": "forge create --rpc-url https://arb-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY --private-key $DEPLOYER_PRIVATE_KEY src/YesNoFeedback.sol:YesNoFeedback --constructor-args $ARB1SEPOLIA_SEMAPHORE_ADDRESS --verify",
"deploy.arb1sepolia.yesno": "forge create --chain arbitrum-sepolia --rpc-url https://arb-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY --private-key $DEPLOYER_PRIVATE_KEY src/YesNoFeedback.sol:YesNoFeedback --constructor-args $ARB1SEPOLIA_SEMAPHORE_ADDRESS 'Do you like working at PSE' --verify",
"test": "forge test",
"verify.arb1sepolia.yesno": "forge verify-contract --chain arbitrum-sepolia $ARB1SEPOLIA_YESNOFEEDBACK_ADDRESS src/YesNoFeedback.sol:YesNoFeedback --constructor-args $(cast abi-encode 'constructor(address)' $ARB1SEPOLIA_SEMAPHORE_ADDRESS)"
}
Expand Down
6 changes: 5 additions & 1 deletion contracts/src/BaseFeedback.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ abstract contract BaseFeedback {
address public admin;
uint256 public groupId;
ISemaphore public semaphore;
string public title;
bool public terminated;

error EmptyTitle();
error InvalidFeedback();
error NotAdmin();
error Terminated();

constructor(address semaphoreAddress) {
constructor(address semaphoreAddress, string memory _title) {
if (bytes(_title).length == 0) revert EmptyTitle();
admin = msg.sender;
terminated = false;
semaphore = ISemaphore(semaphoreAddress);
groupId = semaphore.createGroup(address(this));
title = _title;
}

modifier onlyAdmin() {
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/FreeTextFeedback.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.7 <0.9.0;

import "./BaseFeedback.sol";
import {BaseFeedback} from "./BaseFeedback.sol";

contract FreeTextFeedback is BaseFeedback {
constructor(address semaphoreAddress) BaseFeedback(semaphoreAddress) {}
constructor(address semaphoreAddress, string memory title) BaseFeedback(semaphoreAddress, title) {}

function isValidFeedback(uint256 feedbackHash) internal pure override returns (bool) {
return feedbackHash != 0;
Expand Down
6 changes: 4 additions & 2 deletions contracts/src/MultipleChoiceFeedback.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.7 <0.9.0;

import "./BaseFeedback.sol";
import {BaseFeedback} from "./BaseFeedback.sol";

contract MultipleChoiceFeedback is BaseFeedback {
string[] public options;

error InsufficientOptions();

constructor(address semaphoreAddress, string[] memory _options) BaseFeedback(semaphoreAddress) {
constructor(address semaphoreAddress, string[] memory _options, string memory title)
BaseFeedback(semaphoreAddress, title)
{
if (_options.length < 2) {
revert InsufficientOptions();
}
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/YesNoFeedback.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

pragma solidity >=0.8.7 <0.9.0;

import "./BaseFeedback.sol";
import {BaseFeedback} from "./BaseFeedback.sol";

contract YesNoFeedback is BaseFeedback {
constructor(address semaphoreAddress) BaseFeedback(semaphoreAddress) {}
constructor(address semaphoreAddress, string memory title) BaseFeedback(semaphoreAddress, title) {}

function isValidFeedback(uint256 feedback) internal pure override returns (bool) {
return feedback <= 1;
Expand Down
21 changes: 2 additions & 19 deletions contracts/test/FreeTextFeedback.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ contract FreeTextFeedbackTest is Test {
uint256 private nullifier = 456;
uint256 private feedbackHash = uint256(keccak256(abi.encodePacked("This is a valid feedback")));
uint256[8] private points;
string title = "Free Text Feedback";

function setUp() public {
mockSemaphore = new MockSemaphore();
freeTextFeedback = new FreeTextFeedback(address(mockSemaphore));
freeTextFeedback = new FreeTextFeedback(address(mockSemaphore), title);
}

function test_Constructor() public {
Expand Down Expand Up @@ -75,22 +76,4 @@ contract FreeTextFeedbackTest is Test {
vm.expectRevert(BaseFeedback.InvalidFeedback.selector);
freeTextFeedback.sendFeedback(merkleTreeDepth, merkleTreeRoot, nullifier, 0, points);
}

function testFuzz_ValidFeedback(string memory feedback) public {
vm.assume(bytes(feedback).length > 0);
uint256 feedbackHash = uint256(keccak256(abi.encodePacked(feedback)));
uint256[8] memory points;

vm.expectEmit(true, true, true, true);
emit ISemaphore.ProofValidated(
freeTextFeedback.groupId(),
merkleTreeDepth,
merkleTreeRoot,
nullifier,
feedbackHash,
freeTextFeedback.groupId(),
points
);
freeTextFeedback.sendFeedback(merkleTreeDepth, merkleTreeRoot, nullifier, feedbackHash, points);
}
}
5 changes: 3 additions & 2 deletions contracts/test/MultipleChoiceFeedback.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ contract MultipleChoiceFeedbackTest is Test {
uint256 private nullifier = 456;
uint256[8] private points;
string[] private testOptions;
string title = "Multiple Choice Feedback";

function setUp() public {
mockSemaphore = new MockSemaphore();
testOptions = ["Option A", "Option B", "Option C"];
multipleChoiceFeedback = new MultipleChoiceFeedback(address(mockSemaphore), testOptions);
multipleChoiceFeedback = new MultipleChoiceFeedback(address(mockSemaphore), testOptions, title);
}

function test_Constructor() public view {
Expand Down Expand Up @@ -65,7 +66,7 @@ contract MultipleChoiceFeedbackTest is Test {
insufficientOptions[0] = "Only Option";

vm.expectRevert(MultipleChoiceFeedback.InsufficientOptions.selector);
new MultipleChoiceFeedback(address(mockSemaphore), insufficientOptions);
new MultipleChoiceFeedback(address(mockSemaphore), insufficientOptions, title);
}

function test_JoinGroup() public {
Expand Down
13 changes: 11 additions & 2 deletions contracts/test/YesNoFeedback.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ contract YesNoFeedbackTest is Test {
uint256 private merkleTreeRoot = 123;
uint256 private nullifier = 456;
uint256[8] private points;
string private title = "Yes/No Feedback";

function setUp() public {
mockSemaphore = new MockSemaphore();
yesNoFeedback = new YesNoFeedback(address(mockSemaphore));
yesNoFeedback = new YesNoFeedback(address(mockSemaphore), title);
}

function test_Constructor() public view {
Expand All @@ -30,6 +31,15 @@ contract YesNoFeedbackTest is Test {
assertEq(yesNoFeedback.admin(), address(this));
}

function test_RevertConstructorIfNoTitle() public {
vm.expectRevert(BaseFeedback.EmptyTitle.selector);
new YesNoFeedback(address(mockSemaphore), "");
}

function test_Title() public {
assertEq(yesNoFeedback.title(), title);
}

function test_JoinGroup() public {
yesNoFeedback.joinGroup(idCommitment);
assertEq(mockSemaphore.membersCount(), 1);
Expand All @@ -54,7 +64,6 @@ contract YesNoFeedbackTest is Test {

function test_RevertSendFeedbackIfTerminated() public {
yesNoFeedback.terminate();
uint256[8] memory points;

vm.expectRevert(BaseFeedback.Terminated.selector);
yesNoFeedback.sendFeedback(merkleTreeDepth, merkleTreeRoot, nullifier, 1, points);
Expand Down

0 comments on commit 733e52e

Please sign in to comment.