Polygon ID State Replication: Smart contracts reference
LightweightStateV2
It's a modified state contract meant for the destination chains. It checks a TSS from the Rarimo validators instead of a ZKP to transit the state and only holds a partial history. The relayer service lazily updates the contract whenever a user wants to submit ZKP on a particular chain.
Deployments
Chain | ChainID | Address |
---|---|---|
Sepolia | 11155111 | 0x4EaEdFbD2156f5D77b11c4fE073032c4D90Dd315 (Etherscan) |
Interface
contract LightweightStateV2 is ILightweightStateV2, UUPSSignableUpgradeable, Signers {
address public override sourceStateContract;
uint256 internal _currentGistRoot;
mapping(uint256 => GistRootData) internal _gistsRootData;
mapping(uint256 => IdentityInfo) internal _identitiesInfo;
function signedTransitGISTData(
uint256 prevGist_,
GistRootData calldata gistData_,
bytes calldata proof_
) external override {
// ...
emit SignGISTDataTransited(gistData_.root, prevGist_);
}
function signedTransitStateData(
uint256 prevState_,
StateData calldata stateData_,
bytes calldata proof_
) external override {
// ...
emit SignStateDataTransited(stateData_.id, stateData_.state, prevState_);
}
}
sourceStateContract
— address of the state contract on the source chain (Rarimo);_currentGistRoot
— the latest transferred GIST root;_gistsRootData
— mapping of the GIST roots to their data. Data stores two roots, one that replaced the other, timestamp and block number;_identitiesInfo
— mapping of the identity IDs to the information about this identity. Information has the latest identity state and the history of the states with timestamps;signedTransitGISTData()
— adds the GIST root to the history and changes the current root variable if the proposed one is newer;signedTransitStateData(...)
— adds the state to the history and sets the last state of the identity to the provided one if it's newer;
Both functions require proof of change — TSS of Rarimo signature providers. Also, core functions emit events, which contain the data about changes:
SignGISTDataTransited
contains the data about roots, the previous one and the provided one;SignStateDataTransited
contains the provided identity state, previous state, and identity ID;
See LightweightStateV2.sol for the full implementation.
QueryVerifier
It's an implementation of a verifier contract that inherits Iden3 ZKPVerifier that mints an SBT. It is configured to work with the KYCAge demo credential.
Deployments
Chain | ChainID | Address |
---|---|---|
Sepolia | 11155111 | 0xb95734f64f242E976E155594E1E15D39700Cbb26 (Etherscan) |
Interface
contract QueryVerifier is IQueryVerifier, ZKPVerifier {
uint256 public constant AGE_VERIFY_REQUEST_ID = 1;
IVerifiedSBT public override sbtContract;
mapping(address => uint256) public override addressToUserId;
mapping(uint256 => VerificationInfo) internal _verificationsInfo;
function _beforeProofSubmit(
uint64,
uint256[] memory inputs_,
ICircuitValidator
) internal override {
require(
!isUserVerified(_getIdentityId(inputs_)),
"QueryVerifier: identity with this identifier has already been verified"
);
require(
addressToUserId[msg.sender] == 0,
"QueryVerifier: current address has already been used to verify another identity"
);
}
function _afterProofSubmit(
uint64,
uint256[] memory inputs_,
ICircuitValidator
) internal override {
uint256 tokenId_ = sbtContract.nextTokenId();
uint256 userId_ = _getIdentityId(inputs_);
_verificationsInfo[userId_] = VerificationInfo(msg.sender, tokenId_);
addressToUserId[msg.sender] = userId_;
sbtContract.mint(msg.sender);
emit Verified(userId_, msg.sender, tokenId_);
}
}
AGE_VERIFY_REQUEST_ID
— hard-coded KYC demo request ID;sbtContract
— address of the SBT contract, which will be called to mint Soulbound token;addressToUserId
— mapping of addresses to user's identity ID;_verificationsInfo
— mapping of user's identity ID to the verification information, which contains the prover address and minted token ID;_beforeProofSubmit
— hook that performs some necessary security checks;_afterProofSubmit
— another hook, which mints the SBT in case of valid verification;
The function that verifies the ZKP - verify(...)
is inherited from the ZKPVerifier contract.
See QueryVerifier.sol for the full implementation.
VerifiedSBT
The SBT is awarded to users who complete the Polygon ID x Rarimo demo.
Deployments
Chain | ChainID | Address |
---|---|---|
Sepolia | 11155111 | 0x8A55c9CfDCbCeDcA1A543295a3F54351C335A20f (Etherscan) |
Interface
contract VerifiedSBT is
IVerifiedSBT,
UUPSUpgradeable,
ERC721EnumerableUpgradeable,
OwnableUpgradeable
{
address public override verifier;
uint256 public override nextTokenId;
string public override tokensURI;
// ...
function mint(address recipientAddr_) external override onlyVerifier {}
function _beforeTokenTransfer(
address from_,
address to_,
uint256 firstTokenId_,
uint256 batchSize_
) internal override {
// ...
}
}
verifier
— address of the verifier's (QueryVerifier
) contract;nextTokenId
— nonce that is incremented each time a new SBT is created;tokensURI
— token's picture URI;onlyVerifier()
— modifier that allows calls only by the verifier contract;mint(address)
— mints the SBT for the given address;_beforeTokenTransfer(...)
— prevents the token from being transferred (only burn and mint are available);
See VerifiedSBT.sol for the full implementation.