🤖Usage and Contract

Overview

The Veryfi contract facilitates the process of verifying ownership of tokens across various blockchain networks. This includes NFTs, ERCs, staked tokens, or any other tokens that implement the balanceOf function. The contract works by interacting with the Morpheus oracle to fetch crosschain data about the user's balance.

Veryfi Deployed Addresses

Sepolia/Optimism/Arbitrum/Base 0x0000Ad609D5167e87DC7456fbf6AB5FBf2fB08a7

Bootstrap NFT Gatekeeper contract using Veryfi for Ethereum

Here's a sample contract to show how easy it is to Veryfi assets. Simply put in the Veryfi address for the chain you're using, the NFT address for your NFT to check ownership, and set the ChainID for the NFT you're looking to verify ownership and you're ready to use Veryfi.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

interface ICrosschainLookup {
    function getBalance(address target, address TOKEN, uint chainID) external payable;
    function checkBalance(address user, address token,uint chainID ) external view returns (uint256);
    function fee() external view returns (uint);
}

contract NFTWhitelister {
    ICrosschainLookup public veryfi;
    address public NFT;   // The NFT we want to check
    mapping(address => bool) public whitelisted; // To store whitelisted users
    uint public chainID = 1;
    
    constructor(address _veryfiAddress, address _desiredNFT, uint ID) {
        veryfi = ICrosschainLookup(_veryfiAddress);
        NFT = _desiredNFT;
        chainID = ID;
    }

    // Request to check if a holder possesses the desired NFT on another chain
    function requestNFTVerification(address holder, uint chainID) external payable {
        uint feeRequired = veryfi.fee();
        require(msg.value >= feeRequired, "Insufficient fee sent");
        veryfi.getBalance{value: feeRequired}(holder, NFT, chainID);
    }
    // Whitelist the user if they possess the desired NFT on another chain
    function whitelistUser(address holder, uint chainID) external {
        uint256 nftBalance = veryfi.checkBalance(holder, NFT, chainID);
        require(nftBalance > 0, "Holder does not possess the desired NFT");

        whitelisted[holder] = true;
    }

    function isWhitelisted(address holder) external view returns (bool) {
        return whitelisted[holder];
    }
}

You can also skip the request verification by simply getting your users to go to https://veryfi.xyz/ to verify their assets first. Then you can simply

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

interface ICrosschainLookup {
    function userBalance(uint chainID, address user, address token) external view returns (uint256);
    }

contract NFTWhitelister {
    mapping(address => bool) public whitelisted; // To store whitelisted users

    // Whitelist the user if they possess the desired NFT on another chain
    // 1 assumes ETH for chainID
    function whitelistUser(address holder) external {
        uint256 nftBalance = ICrosschainLookup(veryfiADDRSHERE).userBalance(1, holder, NFTADDRESSHERE);
        require(nftBalance > 0, "Holder does not possess the desired NFT");
        whitelisted[holder] = true;
    }

    function isWhitelisted(address holder) external view returns (bool) {
        return whitelisted[holder];
    }
}

Contract Interface

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

interface ICrosschainLookup {
    function getMyBalance(address TOKEN, uint chainID) external payable;
    function getBalance(address target, address TOKEN, uint chainID) external payable;
    function checkBalance(address user, address token,uint chainID ) external view returns (uint256);
    function setMyBalance(address token, uint chainID) external;
    function setBalance(address target, address token, uint chainID) external;

    function userBalance(uint chainID, address user, address token) external view returns (uint256);
    function userBalanceFeed(uint chainID, address user, address token) external view returns (uint256);
    function fee() external view returns (uint256);
}

ICrosschainLookup Interface Documentation

Description

ICrosschainLookup is an interface for querying and setting user balances across different blockchain networks. The contract allows users to retrieve their own balance or the balance of other users for a specific token and chain ID. The balances are fetched from external sources and stored within the contract.

Functions

1. getMyBalance

function getMyBalance(address TOKEN, uint chainID) external payable;

Parameters:

  • TOKEN (type: address): The contract address of the token you want to query the balance for.

  • chainID (type: uint): The ID of the blockchain network you're querying. If set to 0, it defaults to 1.

Description: Allows the caller to query their own balance for a specific token on a specific blockchain network. The function requires a fee to be sent along with the transaction.

2. getBalance

function getBalance(address target, address TOKEN, uint chainID) external payable;

Parameters:

  • target (type: address): The address of the user whose balance you want to query.

  • TOKEN (type: address): The contract address of the token you want to query the balance for.

  • chainID (type: uint): The ID of the blockchain network you're querying. If set to 0, it defaults to 1.

Description: Allows the caller to query the balance of a specific user for a specific token on a specific blockchain network. The function requires a fee to be sent along with the transaction.Function Documentation: checkBalance

3. checkBalance

function checkBalance(
    address target,
    address token,
    uint chainID
) public view returns (uint256 balance, uint256 timestamp);

Description

The checkBalance function in the Veryfi contract is designed to retrieve the balance and the timestamp of the last update for a specific token held by a given address (target) on a specified blockchain network (identified by chainID). This function is particularly useful for verifying token balances across multiple blockchain networks, enhancing functionalities such as cross-chain asset verification and management.

Parameters

  • address target: The address of the user whose token balance is being queried. This parameter specifies the account for which the balance information is required.

  • address token: The contract address of the token for which the balance is being queried. This should be the address of the ERC-20 or similar token contract.

  • uint chainID: The identifier of the blockchain network on which the token balance is to be checked. If the value is set to 0, it defaults to 1, which corresponds to the Ethereum mainnet.

Returns

  • uint256 balance: The balance of the specified token held by the target address. This balance is retrieved from the Morpheus oracle feed or from the contract’s stored balance if the oracle feed is not available or up to date.

  • uint256 timestamp: The timestamp of the last update to the balance. This indicates when the balance was last fetched or confirmed, providing a reference for the data's recency and relevance.

Usage

This function is typically used in scenarios where an application or contract needs to verify the token holdings of a user across different blockchain networks. It leverages the Morpheus oracle for fetching the balance, providing an efficient way to access cross-chain data.

Important Notes

  • The balance and timestamp are returned as is, meaning the calling function or user needs to interpret these values in the context of the token’s decimal places and the blockchain’s timekeeping.

  • If the Morpheus oracle has not provided an update or the feed is unavailable, the function returns the stored balance and timestamp in the contract, which might not reflect the most current state.

Example

address userAddress = 0x123...; // User's address
address tokenAddress = 0xABC...; // Token's contract address
uint chainId = 1; // Ethereum mainnet

// Call the checkBalance function
(uint256 userBalance, uint256 lastUpdatedTimestamp) = contractInstance.checkBalance(userAddress, tokenAddress, chainId);

// Use the returned balance and timestamp as needed

This function is essential in the broader context of the Veryfi contract, particularly for applications that need to validate token ownership or balances across multiple chains, such as in the case of multi-chain wallets, cross-chain decentralized applications (dApps), or for compliance and auditing purposes in DeFi platforms.

3. setMyBalance

function setMyBalance(address token, uint chainID) external;

Parameters:

  • token (type: address): The contract address of the token for which you've previously fetched the balance.

  • chainID (type: uint): The ID of the blockchain network you've fetched the balance from.

Description: Allows the caller to set their balance for a specific token on a specific blockchain network, after they've fetched it using getMyBalance.

setBalance

function setBalance(address target, address token, uint chainID) external;

Parameters:

  • target (type: address): The address of the user whose balance you've fetched and want to set.

  • token (type: address): The contract address of the token for which you've fetched the balance.

  • chainID (type: uint): The ID of the blockchain network you've fetched the balance from.

Description: Allows the caller to set the balance of a specific user for a specific token on a specific blockchain network, after they've fetched it using getBalance.

5. userBalance

function userBalance(uint chainID, address user, address token) external view returns (uint256);

Parameters:

  • chainID (type: uint): The ID of the blockchain network you want to get the stored balance from.

  • user (type: address): The address of the user whose stored balance you want to retrieve.

  • token (type: address): The contract address of the token you want to get the stored balance for.

Returns:

  • uint256: The stored balance of the user for the specified token on the specified blockchain network.

Description: Returns the stored balance of a specific user for a specific token on a specific blockchain network.

6. userBalanceFeed

function userBalanceFeed(uint chainID, address user, address token) external view returns (uint256);

Parameters:

  • chainID (type: uint): The ID of the blockchain network you want to get the feed ID from.

  • user (type: address): The address of the user whose feed ID you want to retrieve.

  • token (type: address): The contract address of the token you want to get the feed ID for.

Returns:

  • uint256: The feed ID associated with the user's balance fetch operation for the specified token on the specified blockchain network.

Description: Returns the feed ID associated with a user's balance fetch operation for a specific token on a specific blockchain network. This feed ID can be used to fetch the balance from an external source.

7. fee

function fee() external view returns (uint256);

Returns:

  • uint256: The current fee amount required to query balances.

Description: Returns the current fee amount (in wei) that users need to send along with their transaction when querying their balance or the balance of another user. This fee is set by the contract owner and is used to compensate for the oracle costs associated with querying balances from external sources.

Notes:

  • Always double-check the chainID to make sure you're querying the correct blockchain network.

  • Fees are required for balance fetch operations (getMyBalance and getBalance), ensure you send the correct fee amount when calling these functions.

  • setBalance can only be used once the oracle has submitted the balance to the network, this usually takes between 15-60s. You can send a larger fee using getBalance to ensure the oracle will process the request during high use. You can also explore the Morpheus docs here for being able to reping requests, increase the bounty to fill a request. https://docs.scry.finance/docs/morpheus/use-request-feeds

Supported Chains

Ethereum Chain ID 0

Optimism Chain ID 10

Arbitrum Chain ID 42161

Base Chain ID 8453

Polygon Chain ID 137

Veryfi.sol

Constructor

The constructor initializes the RPC mapping with default RPC endpoints for various blockchain networks. It also sets the owner to the address that deploys the contract.

Functions and Specs

1. getMyBalance(address TOKEN, uint chainID) public payable

Fetches the balance of the caller's token on a specific chain.

  • TOKEN: Address of the token contract.

  • chainID: The ID of the blockchain network. If set to 0, it defaults to 1 (Ethereum mainnet).

2. getBalance(address target, address TOKEN, uint chainID) public payable

Fetches the balance of a specified address's token on a particular chain.

  • target: Address of the user whose balance needs to be fetched.

  • TOKEN: Address of the token contract.

  • chainID: The ID of the blockchain network. If set to 0, it defaults to 1 (Ethereum mainnet).

3. addressToBytes(address _address) public pure returns (bytes memory)

Converts an address to bytes.

  • _address: The address to be converted.

4. bytesToHexString(bytes memory data) public pure returns (string memory)

Converts bytes data to a hex string.

  • data: The bytes data to be converted.

5. changeOwnerFEEAndRPC(address Own, uint nfee, string memory newRPC, uint i) public

Changes the contract owner, the fee, and the RPC endpoint of a specific chain. Only the owner can call this function.

  • Own: The new owner's address.

  • nfee: The new fee value.

  • newRPC: The new RPC endpoint.

  • i: The chain ID for which the RPC endpoint needs to be updated.

6. setMyBalance(address token, uint chainID) public

Sets the balance of the caller's token on a specific chain.

  • token: Address of the token contract.

  • chainID: The ID of the blockchain network. If set to 0, it defaults to 1 (Ethereum mainnet).

7. setBalance(address target, address token, uint chainID) public

Sets the balance of a specified address's token on a specific chain.

  • target: Address of the user whose balance needs to be set.

  • token: Address of the token contract.

  • chainID: The ID of the blockchain network. If set to 0, it defaults to 1 (Ethereum mainnet).

Important Notes

  1. The contract relies on the Morpheus oracle to fetch crosschain data. The oracle's results are then stored in the userBalance mapping.

  2. The contract requires a fee (fee) to be paid when making requests to the Morpheus oracle.

  3. The owner of the contract has the ability to change the contract's fee, the owner address itself, and the RPC endpoints for different chains.

Last updated