Sismo Solidity Library
Integrate Sismo Badges into your Solidity smart contracts
âUsingSismo.sol is a Solidity library that allows any smart contract developer to integrate Sismo Badges with their Solidity projects.
The following documentation aims at presenting the three core functions of the UsingSismo library:
_requireBadge
to check if a user holds certain Sismo Badges;onlyBadgeHolders
to use_requireBadge
to restrict access to a function based on a user's Sismo Badge balance;_mintSismoBadge
to mint a Sismo Badge with a valid Sismo proof.
If you want to see the Solidity contract of the UsingSismo library, you can go to our Sismo Protocol repository. You can also find a live application, zkdrop.io that has implemented a privacy-preserving NFT airdrop contract integrating the Using Sismo library.
function _requireBadge(address account, uint256 badgeTokenId) internal view;
Parameter Name | Type | Description |
---|---|---|
account | address | user address |
badgeTokenId | uint256 | tokenId of the required badge |
This function should:
- Check if the account has the required Badge
- Revert if the account does not have the required Badge
By default, this function takes only one
badgeTokenId
as a parameter and checks that the account
holds the Badge with at least a level (balance) of 1.
However, you are free to use more advanced functions that let you personalize your requirements to check the level (balance) of multiple Badges for a user.For example, you could check that a user holds three different Badges (with three different badgeTokenIds) with a level greater or equal to 2 for all these Badges.
function _requireBadges(
address account,
uint256[] memory badgeTokenIds,
bool isEachBadgeRequired, // default = false
uint256[] memory requiredBalances, // default = [1, .., 1]
BalanceRequirementType balanceRequirementType // default = [gte]
) internal view;
â
modifier onlyBadgeHolders(uint256 badgeTokenId);
Parameter Name | Type | Description |
---|---|---|
badgeTokenId | uint256 | tokenId of the required badge |
This modifier should:
- Check if the
msg.sender
has the required Badge - Revert if the account does not have the required Badge
Modifiers of the UsingSismo library are basically calling
_requireBadge
functions. Therefore, you have more advanced modifiers available in the library for different use cases. You can see the code of the modifiers here.function _mintSismoBadge(
Request memory request,
bytes memory sismoProof,
) internal returns (address, uint256, uint256);
Parameter Name | Type | Description |
---|---|---|
request | Request | A user request with a set of claims and a destination |
sismoProof | bytes | Arbitrary data required by an attester to validate the request |
Returns
Type | Description |
---|---|
address | Owner of the newly minted Badge |
uint256 | The newly minted Badge tokenId |
uint256 | The newly minted Badge level |
This function should:
- Mint a Sismo Badge by calling Sismo's
HydraS1AccountboundAttester
contract with a validrequest
alongside itssismoProof
- Return the newly minted Badge owner, tokenId, and level.
- Revert if the
sismoProof
is not proving the user request.
You can see the user request struct here.
The
SismoProof
argument is bytes
that will prove that the request
is valid. The easiest way to obtain the request
and the SismoProof
is by using the 'Prove with Sismo' off-chain flow that will be soon unveiled. The "Prove With Sismo" off-chain flow allows users to prove that they are eligible for a specific Sismo Badge and mint it on-chain thanks to a Sismo proof and a request.
By default, this function calls Sismo's
HydraS1AccountboundAttester
contract. However, you can also call another attester by specifying its address in the _mintSismoBadge
function that takes the address of an attester as a third argument.function _mintSismoBadge(
Request memory request,
bytes memory sismoProof,
address attester
) public returns (address, uint256, uint256)
Here are some code snippets used to gate access to an NFT airdrop to certain Sismo Badge holders with the UsingSismo library. The following snippets are very simple, so if you want to see a contract actually leveraging UsingSismo library, you can read this contract.
First, we want our contract to inherit from UsingSismo.sol. We can pass a gatingBadgeTokenId in the constructor, it will be the required Sismo Badge to hold to access the NFT airdrop.
contract ZKDrop is ERC721, UsingSismo {
uint256 public immutable GATING_BADGE_TOKEN_ID;
constructor(uint256 gatingBadgeTokenId) ERC721("ZKDrop", "ZKD") {
GATING_BADGE_TOKEN_ID = gatingBadgeTokenId;
}
// contract code
}
We can then create a gated
claimTo
function using the modifier onlyBadgeHolders
. If to
holds the Badge with a Badge TokenId equal to GATING_BADGE_TOKEN_ID
, the function will mint the ERC721 with the inputted tokenId
on its address. Else, it will revert, effectively gating the
claimTo
function.function claimTo(address to, uint256 tokenId) public onlyBadgeHolders(GATING_BADGE_TOKEN_ID) {
_mint(_msgSender(), tokenId);
}
The
claimTo
function is interesting, yet does not allow minting a Badge and an ERC721 in the same transaction. For this use case, you could use another function that takes a request
, a sismoProof
and an ERC721 tokenId
as inputs.If the
sismoProof
is valid, a new Badge will be minted on destination
. We then call claimTo
to mint an ERC721 on destination
. If the
sismoProof
is invalid, the function will revert, and no Badge nor ERC721 will be minted.function claimWithSismo(
Request memory request,
bytes memory sismoProof,
uint256 tokenId
) public {
(address destination, , ) = _mintSismoBadge(request, sismoProof);
claimTo(destination, tokenId);
}
Again, a contract used in production can be seen here if you are interested in learning more about how to integrate Sismo Badges into your contracts.