+ {" "}
+ Notes:
+ 1. If you are using metamask and transactions hang. Go to settings > advanced > clear activity and nonce data
+ 2. First ZK Proof generation takes longer time, especially with bad internet as there is a
+ zkey file to download once in the data vault connection
+ 3. The more proofs you request, the longer it takes to generate them (about 2 secs per
+ proof)
+
>
);
diff --git a/front/src/app/globals.css b/front/src/app/globals.css
index 9707953..66f1a08 100644
--- a/front/src/app/globals.css
+++ b/front/src/app/globals.css
@@ -158,11 +158,12 @@ input:focus {
.callout {
- color: #d3d3d3; /* Light gray color */
+ color: #000000; /* Black color text */
padding: 1rem; /* Adds some space around the text */
- border: 1px solid #d3d3d3; /* Adds a light gray border */
+ border: 2px solid #000000; /* Increases border thickness and change to black */
border-radius: 5px; /* Rounds the corners of the border */
- background-color: rgba(0,0,0,0.1); /* Adds a very light black background to increase readability of gray text */
+ background-color: rgba(255,255,255,0.6); /* Adds a semi-transparent white background to increase readability of black text */
+ box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); /* Adds a slight shadow for a "lifted" effect */
}
.verifying, .verified {
diff --git a/front/src/app/page.tsx b/front/src/app/page.tsx
index ea7b384..b6806ee 100644
--- a/front/src/app/page.tsx
+++ b/front/src/app/page.tsx
@@ -60,7 +60,7 @@ export default function Home() {
<>
<>
{" "}
-
+ {pageState != "init" && }
{`Chain: ${chain?.name} [${chain?.id}]`}
@@ -71,30 +71,22 @@ export default function Home() {
<>
{
setResponseBytes(responseBytes);
}}
// Some text to display on the button
text={"Claim with Sismo"}
/>
-
- {" "}
- Notes:
- 1. First ZK Proof generation takes longer time, especially with bad internat as
- there is a zkey file to download once in the data vault connection
- 2. The more proofs you request, the longer it takes to generate them (about 2 secs
- per proof)
-
>
)}
diff --git a/front/src/app/sismo-connect-config.ts b/front/src/app/sismo-connect-config.ts
index 65614b1..1e5afa8 100644
--- a/front/src/app/sismo-connect-config.ts
+++ b/front/src/app/sismo-connect-config.ts
@@ -35,6 +35,7 @@ export const CONFIG: SismoConnectConfig = {
// Sismo Connect Response in the vault instead of redirecting back to the app
};
+// Request users to prove ownership of a Data Source (Wallet, Twitter, Github, Telegram, etc.)
export const AUTHS: AuthRequest[] = [
// Anonymous identifier of the vault for this app
// vaultId = hash(vaultSecret, appId).
@@ -46,6 +47,7 @@ export const AUTHS: AuthRequest[] = [
// { authType: AuthType.TELEGRAM, userId: "875608110", isOptional: true },
];
+// Request users to prove membership in a Data Group (e.g I own a wallet that is part of a DAO, owns an NFT, etc.)
export const CLAIMS: ClaimRequest[] = [
{
// claim on Sismo Hub GitHub Contributors Data Group membership: https://factory.sismo.io/groups-explorer?search=0xda1c3726426d5639f4c6352c2c976b87
@@ -71,11 +73,12 @@ export const CLAIMS: ClaimRequest[] = [
// request user to prove membership in the group with value = 10
groupId: "0xfae674b6cba3ff2f8ce2114defb200b1",
claimType: ClaimType.EQ,
- value: 10, // dhadrin.sismo.eth minted exactly 10, eligible
+ value: 10, // dhadrien.sismo.eth minted exactly 10, eligible
isOptional: true,
},
];
+// Request users to sign a message
export const SIGNATURE_REQUEST: SignatureRequest = {
message: "I love Sismo!",
isSelectableByUser: true,
diff --git a/front/src/utils/useContract.tsx b/front/src/utils/useContract.tsx
index 20b10d9..bb6777f 100644
--- a/front/src/utils/useContract.tsx
+++ b/front/src/utils/useContract.tsx
@@ -84,15 +84,14 @@ export default function useContract({
let txReceipt: TransactionReceipt | undefined;
if (chain.id === 5151111) {
const timeout = new Promise((_, reject) =>
- setTimeout(
- () =>
- reject(
- new Error(
- "Local fork error: operation timed out after 15 seconds, if you are running a local fork on Anvil please make sure to reset your wallet nonce."
- )
- ),
- 10000
- )
+ setTimeout(() => {
+ setPageState("responseReceived");
+ reject(
+ new Error(
+ "Transaction timed-out: If you are running a local fork on Anvil please make sure to reset your wallet nonce. In metamask: Go to settings > advanced > clear activity and nonce data"
+ )
+ );
+ }, 10000)
);
const txReceiptPromise = tx && waitForTransaction({ hash: tx.hash });
const race = await Promise.race([txReceiptPromise, timeout]);
diff --git a/src/Airdrop.sol b/src/Airdrop.sol
index 6711e5d..2cd593d 100644
--- a/src/Airdrop.sol
+++ b/src/Airdrop.sol
@@ -3,23 +3,30 @@ pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "forge-std/console.sol";
-import "sismo-connect-solidity/SismoLib.sol"; // <--- add a Sismo Connect import
+import "sismo-connect-solidity/SismoLib.sol";
/*
* @title Airdrop
* @author Sismo
- * @dev Simple Airdrop contract that mints ERC20 tokens to the msg.sender
- * This contract is used for tutorial purposes only
- * It will be used to demonstrate how to integrate Sismo Connect
+ * @dev Simple Airdrop contract gated by Sismo Connect
+ * Application requests multiple zk proofs (auths and claims) and verify them
+ * The contract stores all verified results in storage
*/
contract Airdrop is ERC20, SismoConnect {
error AlreadyClaimed();
+ event AuthVerified(VerifiedAuth verifiedAuth);
+ event ClaimVerified(VerifiedClaim verifiedClaim);
+ event SignedMessageVerified(bytes verifiedSignedMessage);
using SismoConnectHelper for SismoConnectVerifiedResult;
mapping(uint256 => bool) public claimed;
+ // must correspond to requests defined in the app frontend
+ // Sismo Connect response's zk proofs will be checked against these requests.
+ // check Airdrop.s.sol to see how these requests are built and passed to the constructor
AuthRequest[] private _authRequests;
ClaimRequest[] private _claimRequests;
+ // Results of the verification of the Sismo Connect response.
VerifiedAuth[] internal _verifiedAuths;
VerifiedClaim[] internal _verifiedClaims;
bytes internal _verifiedSignedMessage;
@@ -36,66 +43,48 @@ contract Airdrop is ERC20, SismoConnect {
_setClaims(claimRequests);
}
-// struct SismoConnectVerifiedResult {
-// bytes16 appId;
-// bytes16 namespace;
-// bytes32 version;
-// VerifiedAuth[] auths;
-// VerifiedClaim[] claims;
-// bytes signedMessage;
-// }
-
function claimWithSismo(bytes memory response) public {
SismoConnectVerifiedResult memory result = verify({
responseBytes: response,
- // we want the user to prove that he owns a Sismo Vault
- // we are recreating the auth request made in the frontend to be sure that
- // the proofs provided in the response are valid with respect to this auth request
+ // checking response against requested auths
auths: _authRequests,
+ // checking response against requested claims
claims: _claimRequests,
- // we also want to check if the signed message provided in the response is the signature of the user's address
+ // checking response against requested message signature
signature: buildSignature({message: abi.encode(msg.sender)})
});
- for (uint256 i = 0; i < result.auths.length; i++) {
- _verifiedAuths.push(result.auths[i]);
- }
- for (uint256 i = 0; i < result.claims.length; i++) {
- _verifiedClaims.push(result.claims[i]);
- }
-
- _verifiedSignedMessage =result.signedMessage;
-
- // if the proofs and signed message are valid, we take the userId from the verified result
- // in this case the userId is the vaultId (since we used AuthType.VAULT in the auth request),
// it is the anonymous identifier of a user's vault for a specific app
// --> vaultId = hash(userVaultSecret, appId)
+ // used to avoid double claims
uint256 vaultId = result.getUserId(AuthType.VAULT);
- // we check if the user has already claimed the airdrop
- // if (claimed[vaultId]) {
- // revert AlreadyClaimed();
- // }
+ // checking if the user has already claimed
+ if (claimed[vaultId]) {
+ revert AlreadyClaimed();
+ }
- // we mark the user as claimed. We could also have stored more user airdrop information for a more complex airdrop system. But we keep it simple here.
+ // marking that the user has claimed
claimed[vaultId] = true;
+ // airdrop amount = number of verified proofs
uint256 airdropAmount = (result.auths.length + result.claims.length) * 10 ** 18;
_mint(msg.sender, airdropAmount);
- }
- function _setAuths(AuthRequest[] memory auths) private {
- for (uint256 i = 0; i < auths.length; i++) {
- _authRequests.push(auths[i]);
+ // storing the result of the verification
+ for (uint256 i = 0; i < result.auths.length; i++) {
+ _verifiedAuths.push(result.auths[i]);
+ emit AuthVerified(result.auths[i]);
}
- }
-
- function _setClaims(ClaimRequest[] memory claims) private {
- for (uint256 i = 0; i < claims.length; i++) {
- _claimRequests.push(claims[i]);
+ for (uint256 i = 0; i < result.claims.length; i++) {
+ _verifiedClaims.push(result.claims[i]);
+ emit ClaimVerified(result.claims[i]);
}
+ _verifiedSignedMessage =result.signedMessage;
+ emit SignedMessageVerified(result.signedMessage);
}
+
function getVerifiedClaims() external view returns (VerifiedClaim[] memory) {
return _verifiedClaims;
}
@@ -107,4 +96,17 @@ contract Airdrop is ERC20, SismoConnect {
function getVerifiedSignedMessage() external view returns (bytes memory) {
return _verifiedSignedMessage;
}
+
+ function _setAuths(AuthRequest[] memory auths) private {
+ for (uint256 i = 0; i < auths.length; i++) {
+ _authRequests.push(auths[i]);
+ }
+ }
+
+ function _setClaims(ClaimRequest[] memory claims) private {
+ for (uint256 i = 0; i < claims.length; i++) {
+ _claimRequests.push(claims[i]);
+ }
+ }
+
}