Guidelines for Projects to be Integrated with zkLink Nova Point System
This document provides detailed guidance for protocol developers interested in integrating their decentralized applications (dApps), decentralized exchanges (DEXes), or other protocols with the zkLink ecosystem to leverage the Nova points incentive system. By following this guide, developers can create compatible adapters, format data submissions and understand the integration workflow.
The main purpose of this integration is to enable protocols that have successfully integrated with the zkLink Nova system to automatically allocate Nova points to their users.
As the final verification step in this integration process, we will conduct a rigorous comparison between the CSV file generated by your adapter and the actual on-chain data obtained from your contract deployed on the zkLink network.
This comparison is crucial to ensure the accuracy and consistency of the data before finalizing the integration and activating point allocation.
Once the verification is successful, zkLink will start distributing Nova points to users.
Here is a brief overview of the zkLink points framework and components that need to be understood in order to clearly understand the types of points data you need to provide. When users transfer assets from cross-chain bridges to the zkLink Nova network, they can participate in various protocol interactions within the zkLink network ecosystem. We will calculate points based on the assets directly held by users and the metrics generated from interactions with dApps. In the adapters, we collect 3 types of metrics data provided by project parties to calculate EcosystemPoints, the EcosystemPoints formulas is:
-
Volu,t signifies the total volume of trades executed by a user over a period of time.
- DEX, PERPs, Lending, Bridge: The total trading/lending/bridging volume by the user based on the formula above.
- GameFi, NFTFi, SocialFi:
The total trading volume of assets such as NFTFi and SocialFi.
The total spending in the game economy (eg. tokens spent in gameFi, in-game asset trading etc) In this sense, the total trading volume can signify total transaction volume in gameFi. - To prevent sybil attack, a multiplier of 1/x where x = 1000, 2000,..., N is used for each specific protocol. The multiplier is incorporated into the constant b.
-
TVLu,t (Total Locked Value): Total value of liquidity provided to DEX pools or PERPs or Lending Protocol, The TVL refers to the total value of different tokens owned by each user in a specific period of time.
These tokens represent the quantity of underlying tokens corresponding to these collateral certificates in the pool, which is USDC/ETH/WETH etc. Typically, protocols mint LP tokens to users, and these users holding LP tokens share the TVL points of the protocol. If a user transfers their LP tokens to someone else, the points entitlement will be transferred to the new owner of the LP tokens.
TVL points = sum_all tokens ( user’s token balance * price * token multiplier ) * project booster
How to get user’s token balance for TVL point calculation
For TVL point calculation, we take into consideration the balance of tokens locked in the contracts in every 8 hour snapshot. In most cases, for each token, the balance of tokens is calculated by multiplying the share percentage of the pool by the pool’s token balance.
User’s Token Balance = User’s LP share percentage * Pool balance
This means that the subgraph should listen for events where the user's percentage share in the contract changes based on the actions such as Transfer, Mint, Stake, Deposit, etc. And the pool’s balance might change due to the user's trading or borrowing activities. Pool balance here is equivalent to the contract TVL.
Illustrated examples of balance calculation on Nova
Case 1: for lending protocols
Imagine that A deposits 10 ETH to the liquidity pool (LP). Then B comes in and borrows 2 ETH out of the 10 ETH in the LP. Due to the decrease in the contract’s balance, A will only receive points for the 8 ETH left in the pool.
For most lending protocols, as the liquidity pool is mixed, we assume liquidity providers are providing liquidity on a pro-rata basis. For example, if user A provides 10 ETH to an ETH liquidity pool, and gets back 10 ETH.LP tokens. Now if there’re 100 ETH.LP tokens in total supply, then user A has 10/100 = 10 % of the liquidity pool. And if 20 ETH were borrowed, and there are 80 ETH left in the pool, then user A’s balance will be 10%* 80= 8 ETH
User A’s token balance: User A’s LP share percentage * Pool balance = 10% * 80 = 8ETH
Case 2: For uniswap V2 liquidity pool
Imagine that user A deposits 1 ETH and 3000 USDC in a swap liquidity pool, and gets back 1 ETH-USDC LP token, which presents to the tokens deposited. Assuming the total supply of ETH-USDC LP token is 100, and there are 100 ETH and 300,000 USDC in the pool, then user A has 1/100= 1% of the liquidity pool. Afterwards, as the ETH price fluctuates, the pool now has 60 ETH and 500,000 USDC (due to x*y=k mechanism), user A now has 1%*60=0.6 ETH and 1%* 500,000=5000 USDC.
Case 3: For uniswap V3 liquidity pool
As uniswap V3, as users can provide customized liquidity and get their unique LP NFT, we will calculate points for the balance owned by the user’s total NFTs.
NOTE: Team can to specify the conditions for the percentage of user's LP share such as users' participation in a specific contract interaction. However, the formula to calculate user's token balance is always the user's percentage of LP share multiplies by the pool balance of the underlying token in the contract. ie User's LP share percentage * Pool balance
- TxNumu,t signifies the total number of transactions
- For Dex/Perps/Lending protocol, there is no limit to the tx volume.
- For Bridge, it should be Number of bridged transactions.
- For GameFi/NFTFi, it is the total number of on-chain interactions in the protocol.
Check this example,
Requirements:
Create your own adapter directory under the adapters folder, which consists of three parts.
- execution: This directory houses the Node.js execution files for your adapter. It is a complete npm project, with a
package.json
to ensure correct installation of dependencies. The compilation output entry file is located indist/index.js
. It provides the necessary output functionsgetUserTransactionData
andgetUserTVLData
. We will pass the a blockHeight as a parameter, execute your function, and write the results to a CSV file. - subgraph: We strongly recommend using a subgraph as the data source for Execution because it offers more transparent logic and data. We will review your code to ensure the data originates from the blockchain. If you choose to use a subgraph, please build it in this directory. Refer to the example, create your own subgraph, and you can use the npm script
npm run deploy-subgraph:dev -- -p <adapter-name> -n <subgraph-path>
to deploy your subgraph on dev environment.
# change 'example' and 'example-points' to your relevant names
npm run deploy-subgraph:dev -- -p example -n example-points
- data: You can refer to example/data. You don't need to create this data folder as it will be included in .gitignore. We just want to explain what the output CSV file looks like. It will be located in the data directory. We will input a block height as needed and execute the
getUserTransactionData
andgetUserTVLData
functions you expose in theexecution/dist
folder, finally outputting the CSV to the data folder.
The zkLink Nova network is not yet supported in The Graph's list of supported networks. As a result, to create a subgraph on the zkLink Nova network, it is necessary to set up your own hosted service. We have already set up a functional hosted service specifically for creating subgraphs on the zkLink Nova network. Please note the following requirements before proceeding:
- We will provide you with the deployment scripts necessary for local development. However, you need to set a secret environment variable to distinguish the deployment path from other projects and prevent it from being arbitrarily overwritten. see env
- Once the deployment is complete, teams must upload their source code to the subgraph directory.
- We will deploy it from our repository to our official production environment.
-
Copy example/subgraph folder to your own directory and run the following npm script
-
run the following command:
npm run deploy-subgraph:dev -- -p <projectName> -n <subgraphName>
- Upon successful deployment, a subgraph URL will be returned and displayed in your terminal.
Create an execution folder in your project folder, run npm init
, or you can copy the example/execution
folder directly.
In the entry file, you need to export two functions: getUserTransactionData
and getUserTVLData
. These functions should output data that meets the requirements. getUserTransactionData outputs Vol Points & TxNum Points data between two blocks, and getUserTVLData retrieves a snapshot of the TVL Points data for a specific block.
We capture a snapshot every 8 hours at 02:00 UTC, 10:00 UTC, and 18:00 UTC of data distributed by assets per user on a daily basis.Please ensure that we can obtain correct data with any block height as the parameter.
For DEX swaps and opening/closing trades on perpetuals, we calculate users' Volume and Tx Number to determine points. You need to provide the fields corresponding to the table below. Please note, if you do not provide prices, the points for the Tx Number may not be applicable.For the tokenAddress below, we request that you provide data related to the base token, rather than the quote token.
Data Field | Notes | Example | Required for Vol | Required for TxNum |
---|---|---|---|---|
timestamp | block timestamp | 1370000000 | Yes | Yes |
userAddress | User account | 0x7Ac6d25FD5E437cB7c57Aee77aC2d0A6Cb85936C | Yes | Yes |
contractAddress | related contract address | 0xE8a8f1D76625B03b787F6ED17bD746e0515F3aEf | Yes | Yes |
tokenAddress | The ERC20/ERC721 token address involved in the transaction | 0x8280a4e7D5B3B658ec4580d3Bc30f5e50454F169 | Yes | Yes |
decimals | The decimals of token | 18 | Yes | Yes |
price | Price in USD | 3400.23 | Yes | No |
quantity | The quantity of ERC20 assets involved in the transaction | 1892000000000000000 | Yes | Yes |
txHash | Transaction Hash | 0x8dde0e5cec00361984dbab3780af0372fe39930da1337709ebada69f63996170 | Yes | Yes |
nonce | A unique identifier for a transaction, primarily used to distinguish cases where a single transaction contains multiple swap or similar transactions | 23 | Yes | Yes |
symbol | token symbol | WETH | No | No |
For TVL points calculation, you need to provide the balance portion quantity of different tokens locked by all users in the protocol pool at the corresponding block height.
Data Field | Notes | Example | Required |
---|---|---|---|
timestamp | block timestamp | 1370000000 | Yes |
userAddress | User account | 0x7Ac6d25FD5E437cB7c57Aee77aC2d0A6Cb85936C | Yes |
tokenAddress | Underlying token address. eg: WETH address | 0x8280a4e7D5B3B658ec4580d3Bc30f5e50454F169 | Yes |
poolAddress | Each pool’s contract address where the underlying assets are locked or vault address | 0xE8a8f1D76625B03b787F6ED17bD746e0515F3aEf | Yes |
balance | Should be raw data, eg: 0.1 ETH | 100000000000000000 | Yes |
symbol | token symbol | WETH | No |
You can validate whether the script can output a CSV file that meets the data requirements by executing npm run adapter:tvl
and npm run adapter:tx
. If the execution is successful, a CSV file with the corresponding block height will be generated in the data
root folder under the directory you created.
# @params projectName: The name of the folder where the script will be executed.
# @params filePrefix: file prefix, eg: tvl/tx/hourly or any other prefix etc.
# @params startBlock: The starting block number.
# @params endBlock: The ending block number. If you only generate TVL data and do not export the `getUserTransactionData` method, you can use any number.
# for tvl data
# npm run adapter:tvl -- example tvl 350000
npm run adapter:tvl -- <projectName> <filePrefix> <curBlock>
# for tx data
# npm run adapter:tx -- example tx 320000 350000
npm run adapter:tx -- <projectName> <filePrefix> <startBlock> <endBlock>
We will conduct a sampling verification of your CSV results. Teams are required to provide detailed methods of verification, including the approach and information utilized in the verification process.
Teams should submit some transactions, data reference on the blockchain explorer or analytics platform such as Defillama and a detailed verification method etc. We will utilize the data or tools provided you have provided to verify the accuracy and authenticity of the on-chain data.
We will facilitate our comparison of the provided data against the data provided in the generated CSV.
Important Note: If we are unable to verify the authenticity of CSV data, then the PR will be rejected.
Fork a copy of your repository, complete the adapter, and finally submit your PR to the main branch. When submitting your PR, please select the Adapters Template and fill in all the required information in the template.