Add the MicapassBasicClient.sol or MicapassBasicClientInitializable.sol smart contracts to your codebase
MicapassBasicClient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IMicapassBaseVerifier} from "../interfaces/IMicapassBaseVerifier.sol";
contract MicapassBasicClient {
IMicapassBaseVerifier internal _micapass;
// Declare claim topics for function access control
uint256 internal constant CLAIM_TOPIC_KYC = 1000001;
uint256 internal constant CLAIM_TOPIC_WALLET_SCREENING = 1000002;
uint256 internal constant CLAIM_TOPIC_WALLET_RISK_SCREENING = 1000003;
/**
* @dev Requires the set of claims for specific wallet address
* @param walletAddress - user wallet address
* @param requiredClaimTopic - claim topic id that needs to be checked
*/
modifier micapassProtected(
address walletAddress,
uint256 requiredClaimTopic
) {
require(
_micapass.isUserVerifiedForClaim(walletAddress, requiredClaimTopic),
"Lacking required claims"
);
_;
}
constructor(address micapassAddress) {
_setMicapass(micapassAddress);
}
function getMicapass() external view returns (address) {
return address(_micapass);
}
function _setMicapass(address micapassAddress) internal {
require(
IMicapassBaseVerifier(micapassAddress).supportsInterface(
type(IMicapassBaseVerifier).interfaceId
),
"Creator interface is incorrect"
);
_micapass = IMicapassBaseVerifier(micapassAddress);
}
}
MicapassBasicClientInitializable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {IMicapassBaseVerifier} from "../interfaces/IMicapassBaseVerifier.sol";
contract MicapassBasicClientInitializable is Initializable {
IMicapassBaseVerifier internal _micapass;
// Declare claim topics for function access control
uint256 internal constant CLAIM_TOPIC_KYC = 1000001;
uint256 internal constant CLAIM_TOPIC_WALLET_SCREENING = 1000002;
uint256 internal constant CLAIM_TOPIC_WALLET_RISK_SCREENING = 1000003;
/**
* @dev Requires the set of claims for specific wallet address
* @param walletAddress - user wallet address
* @param requiredClaimTopic - claim topic id that needs to be checked
*/
modifier micapassProtected(
address walletAddress,
uint256 requiredClaimTopic
) {
require(
_micapass.isUserVerifiedForClaim(walletAddress, requiredClaimTopic),
"Lacking required claims"
);
_;
}
function getMicapass() external view returns (address) {
return address(_micapass);
}
// solhint-disable-next-line func-name-mixedcase
function __MicapassBasicClient_init(
address micapassAddress
) internal onlyInitializing {
_setMicapass(micapassAddress);
}
function _setMicapass(address micapassAddress) internal {
require(
IMicapassBaseVerifier(micapassAddress).supportsInterface(
type(IMicapassBaseVerifier).interfaceId
),
"Creator interface is incorrect"
);
_micapass = IMicapassBaseVerifier(micapassAddress);
}
}
Step 1.2
Import and inherit fromMicapassBasicClient.sol or MicapassBasicClientInitializable.sol depending on your use case
import {MicapassBasicClientInitializable} from "./MicapassBasicClientInitializable.sol";
contract Client is MicapassBasicClientInitializable, Managerable {
...
Step 2. Initialization
Pass actual address of Micapass smart contract to your smart contract during initialization and pass it to __MicapassBasicClient_init method
Use this page to check available networks and actual addresses
function initialize(address micapassAddress) external initializer {
__MicapassBasicClient_init(micapassAddress);
...
implement setMicapass method if you want it to be configurable after initialization:
function setMicapass(
address micapassAddress
) external onlyRole(MANAGER_ROLE) {
_setMicapass(micapassAddress);
}
don't forget to protect calling this method for only authorized addresses (admin, manager, etc)
Pay attention that you will not be able to pass address which doesn't support IMicapassBaseVerifier interface, as the internal _setMicapass method is protected with this check
require(
IMicapassBaseVerifier(micapassAddress).supportsInterface(
type(IMicapassBaseVerifier).interfaceId
),
"Creator interface is incorrect"
);
Step 3. Prepare methods and requirements
Step 3.1
Define your functions that are going to be protected by Micapass
For example it can be
function deposit()
and
function withdraw()
Step 3.2
Define requirements
which address should be checked (sender, receiver, etc)
For example for deposit method the msg.sender should be protected by Micapass, but for withdraw - the receiver, or both, msg.sender + receiver
which proofs this address should be checked for (KYC, WALLET_SCREENING), for example:
deposit - KYC, WALLET_SCREENING
withdraw - only WALLET_SCREENING
Step 4. Protection implementation
Add micapassProtected modifier to each method which should be protected with micapass passing address and claim topic that need to be checked
Examples
example of protection deposit method for msg.sender by checking two claims - KYC and WALLET_SCREENING
function deposit()
external
payable
micapassProtected(msg.sender, CLAIM_TOPIC_KYC)
micapassProtected(msg.sender, CLAIM_TOPIC_WALLET_SCREENING)
{
// logic of deposit
...
example of protection withdraw method for msg.sender by checking claim WALLET_SCREENING
function withdraw()
external
micapassProtected(msg.sender, CLAIM_TOPIC_WALLET_SCREENING)
{
or withdraw if the funds should be withdrawn to different address, so we can check receiver for claim WALLET_SCREENING
function withdrawTo(
address receiver
)
external
mAddressNotZero(receiver)
micapassProtected(receiver, CLAIM_TOPIC_WALLET_SCREENING)
{