Happy Birthday Example
Last updated
Last updated
In the Airdrop example, we showed how to customize verification parameters when integrating Self. In this example, we will demonstrate how to use the attributes contained in a passport to build .
Breakdown of the repo:
The happy-birthday application checks the user's birthday recorded in their passport and, if the birthday is within ±5 days of the current block timestamp, awards the user with USDC.
Just like in the Airdrop example, start by importing the following files:
Since the passport attributes are packed into the proof as revealedData_packed
, import these libraries to extract and handle the data:
The happy-birthday app performs the following verifications:
Scope Check: Confirm that the proof was generated specifically for this app.
Attestation ID Check: Ensure the proof was created using the correct attestation ID for the document used by the app.
Nullifier Registration and Check: Prevent multiple claims by registering and verifying the nullifier. The nullifier is a unique value that corresponds one-to-one with the document without revealing any details.
Proof Verification via IdentityVerificationHub: Validate the proof itself, including additional verifications (e.g., olderThan, forbiddenCountries, and OFAC) as set by the contract.
Birthday Verification:
Verify that the user's date of birth (extracted from the proof) is within ±5 days of the current block.timestamp
.
verifySelfProof
FunctionBelow is an example implementation of verifySelfProof
for the happy-birthday app:
The birthday information is packed into revealedData_packed
in the proof. To verify the birthday, follow these steps:
Convert the Packed Data:
Convert revealedData_packed
into a single bytes
array using the Formatter.fieldElementsToBytes
function.
Extract the Date of Birth:
Use the CircuitAttributeHandler.getDateOfBirth
function to extract the date of birth from the byte array.
Reformat the Date:
The extracted date is in the format DD-MM-YY
, but the Formatter.dateToUnixTimestamp
function expects a YYMMDD
string. Rearrange the data accordingly.
(In this example, the year is hard-coded as "25" to represent the birthday in 2025 at midnight.)
Compare with the Current Time:
Convert the reformatted date to a timestamp and compare it with the current block.timestamp
to check if the difference is within ±5 days.
Below is the helper function _isWithinBirthdayWindow
that implements this logic:
In summary, the birthday comparison requires some data transformation after extracting the date of birth from revealedData_packed
. If you only need to retrieve an attribute, the combination of Formatter.fieldElementsToBytes
and the appropriate function from CircuitAttributeHandler
will suffice.
This example demonstrates how to leverage passport attributes—specifically the date of birth—to implement custom logic in your smart contract integration. Adjust the implementation as needed for your application's requirements.