Skip to content

Commit

Permalink
fix: cleaned app and contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
dhadrien committed Jul 17, 2023
1 parent c3b4576 commit d00e7d8
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ docs/
.env

# Sismo connect config
sismo-connect-config.json
sismo-connect-config.json
103 changes: 103 additions & 0 deletions abi/Airdrop.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,109 @@
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{
"internalType": "enum AuthType",
"name": "authType",
"type": "uint8"
},
{
"internalType": "bool",
"name": "isAnon",
"type": "bool"
},
{
"internalType": "uint256",
"name": "userId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "proofData",
"type": "bytes"
}
],
"indexed": false,
"internalType": "struct VerifiedAuth",
"name": "verifiedAuth",
"type": "tuple"
}
],
"name": "AuthVerified",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{
"internalType": "enum ClaimType",
"name": "claimType",
"type": "uint8"
},
{
"internalType": "bytes16",
"name": "groupId",
"type": "bytes16"
},
{
"internalType": "bytes16",
"name": "groupTimestamp",
"type": "bytes16"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "proofId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "proofData",
"type": "bytes"
}
],
"indexed": false,
"internalType": "struct VerifiedClaim",
"name": "verifiedClaim",
"type": "tuple"
}
],
"name": "ClaimVerified",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "verifiedSignedMessage",
"type": "bytes"
}
],
"name": "SignedMessageVerified",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down
9 changes: 9 additions & 0 deletions front/src/app/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ const Header: React.FC = () => {
<b className="code-snippet">src/Airdrop.sol</b>: Contract - verify Sismo Connect request,
mint tokens and stores verified claims and auths
</p>
<p className="callout">
{" "}
Notes: <br />
1. If you are using metamask and transactions hang. Go to settings > advanced > clear activity and nonce data <br />
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 <br />
3. The more proofs you request, the longer it takes to generate them (about 2 secs per
proof)
</p>
</div>
</>
);
Expand Down
7 changes: 4 additions & 3 deletions front/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
22 changes: 7 additions & 15 deletions front/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default function Home() {
<>
<>
{" "}
<button onClick={() => resetApp()}>Reset</button>
{pageState != "init" && <button onClick={() => resetApp()}>Reset</button>}
<p>
<b>{`Chain: ${chain?.name} [${chain?.id}]`}</b>
<br />
Expand All @@ -71,30 +71,22 @@ export default function Home() {
<>
<SismoConnectButton
config={CONFIG}
// Auths = Data Source Ownership Requests
// Auths = Data Source Ownership Requests. (e.g Wallets, Github, Twitter, Github)
auths={AUTHS}
// Claims = prove groump membership of a Data Source in a specific Data Group.
// Claims = prove group membership of a Data Source in a specific Data Group.
// (e.g ENS DAO Voter, Minter of specific NFT, etc.)
// Data Groups = [{[dataSource1]: value1}, {[dataSource1]: value1}, .. {[dataSource]: value}]
// When doing so Data Source is not shared to the app.
// Existing Data Groups and how to create one: https://factory.sismo.io/groups-explorer
claims={CLAIMS}
// we ask the user to sign a message
// it will be used onchain to prevent frontrunning
// Signature = user can sign a message embedded in their zk proof
signature={{ message: signMessage(address!) }}
// onResponseBytes calls a 'setResponse' function with the responseBytes returned by the Sismo Vault
// responseBytes = the response from Sismo Connect, will be sent onchain
onResponseBytes={(responseBytes: string) => {
setResponseBytes(responseBytes);
}}
// Some text to display on the button
text={"Claim with Sismo"}
/>
<p className="callout">
{" "}
Notes: <br />
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 <br />
2. The more proofs you request, the longer it takes to generate them (about 2 secs
per proof)
</p>
</>
)}
<div className="status-wrapper">
Expand Down
5 changes: 4 additions & 1 deletion front/src/app/sismo-connect-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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
Expand All @@ -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,
Expand Down
17 changes: 8 additions & 9 deletions front/src/utils/useContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
86 changes: 44 additions & 42 deletions src/Airdrop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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]);
}
}

}

0 comments on commit d00e7d8

Please sign in to comment.