WorldCoin State Replication smart contracts reference
IdentityManager
It's a modified identity contract meant for the destination chains. It checks a TSS from the Rarimo validators 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.
Interface
contract IdentityManager is IIdentityManager, Signers {
uint256 public constant ROOT_EXPIRATION_TIME = 1 hours;
address public sourceStateContract;
uint256 internal _latestRoot;
uint256 internal _latestTimestamp;
mapping(uint256 => RootData) internal _roots;
function signedTransitRoot(
uint256 prevRoot_,
uint256 postRoot_,
uint256 replacedAt_,
bytes calldata proof_
) external override {
// ...
emit SignedRootTransited(prevRoot_, postRoot_, replacedAt_, _latestRoot);
}
}
ROOT_EXPIRATION_TIME
— a fixed time after which the root is considered "expired", i.e., proofs with it are considered invalid after that;sourceStateContract
— address of the state contract on the source chain (Rarimo);_latestRoot
— latest (and newest) transited root;_latestTimestamp
— timestamp of latest root replacement;_roots
— mapping of roots to data about these roots (replacement timestamp and root that replaced this one). It is updated after the transition is done;signedTransitRoot(...)
— the main function that adds the information to the history (_roots
). It changes the_latestRoot
ifpostRoot_
is newer. Requires the threshold signature of Rarimo signature providers. Also, emits theSignedRootTransited
event, which contains information about the transition (both roots, timestamp of replacement, and current latest root);
For the full implementation, see IdentityManager.sol at the GitHub.
Verifier
It's an implementation of a verifier contract.
You can add your business logic to it by modifying (or overriding) two hooks – _beforeProofSubmit
and _afterProofSubmit
;
Interface
contract Verifier is IVerifier, Initializable {
address public semaphoreVerifier;
address public identityManager;
function verifyProof(
uint256 root_,
uint256 signalHash_,
uint256 nullifierHash_,
uint256 externalNullifierHash_,
uint256[8] calldata proof_
) public virtual override {
// ...
_beforeProofValidation();
ISemaphoreVerifier(semaphoreVerifier).verifyProof(
proof_,
[root_, nullifierHash_, signalHash_, externalNullifierHash_]
);
_afterProofValidation();
}
function _beforeProofValidation() internal virtual {}
function _afterProofValidation() internal virtual {}
}
semaphoreVerifier
— address of theSemaphoreVerifier
contract that verifies the proof;identityManager
— address of theIdentityManager
contract;verifyProof(...)
— the main function that verifies the user's proof. It calls theIdentityManager
to verify whether the root is actual andSemaphoreVerifier
to verify the proof itself;_beforeProofValidation()
— hook that should be executed before theverifyProof(...)
;_afterProofValidation()
— hook that gets executed after theverifyProof(...)
call;
For the full implementation, see Verifier.sol at the GitHub.
SemaphoreVerifier
This contract is responsible for verifying the ZKP.
It has some necessary math functions, constants, and the primary verifyProof(...)
function.
It allows proofs to be verified in uncompressed or compressed form.
Usually, uncompressed form is used, see BN254 Point Compression for further explanation.
Interface
contract SemaphoreVerifier is ISemaphoreVerifier {
/* ... */
function verifyCompressedProof(
uint256[4] calldata compressedProof,
uint256[4] calldata input
) public view {
// ...
}
function verifyProof(uint256[8] calldata proof, uint256[4] calldata input) public view {
// ...
}
}
verifyCompressedProof(...)
— verifies a compressed proof;verifyProof(...)
— verifies an uncompressed proof;
For the full implementation, see SemaphoreVerifier.sol at the GitHub.