Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The CrossCurve Consensus Bridge addresses one of the key problems of modern cross-chain solutions — the vulnerability of bridges and the so-called “black swan” risk. A prime example of such a risk is the Multichain incident, after which Curve DAO withdrew its trust from bridges based on centralized governance.
The core issue lies in the fact that most existing bridges are controlled by a limited group of participants — validators or members of multisig groups. This makes them vulnerable and unstable. Classic examples of such failures include hacks or loss of funds in protocols such as Multichain, PolyNetwork, Wormhole, Nomad and Ronin.
Unlike the traditional PoA (proof-of-authority) solutions, the CrossCurve Consensus Bridge uses a validation model based on agreement between independent data transmission protocols. This architecture involves Axelar, LayerZero, Router Protocol, Asterizm and Chainlink CCIP. A transaction is completed only if consensus is reached among multiple sources. If the data diverges, the transaction is automatically rejected, preventing potential compromise and ensuring the safety of user funds.
The user's assets are locked in the consensus bridge smart contract on the source network.
Transaction data is transmitted through multiple protocols simultaneously, and the smart contract of the target network verifies their consistency.
If consensus is reached, the transaction is finalized; otherwise, the funds are returned to the user.
Security: The risk of compromise is minimized thanks to consensus among several protocols — the likelihood of all protocols being hacked at the same time is virtually zero.
Decentralization: Bridge security does not depend on individual teams; the bridge smart contracts are governed by CrossCurve DAO, and the protocol’s liquidity is fully controlled by users.
Versatility: The consensus bridge supports the transmission of both tokens and data, making it a universal tool for cross-chain applications.
Consensus Bridge is not just a bridge—it is the transport layer of the CrossCurve Metalayer, providing a reliable connection between blockchains. It enables developers and users to safely transfer assets, data, and liquidity, forming the foundation for a scalable and resilient cross-chain ecosystem of the future.
CrossCurve MetaLayer is a unified decentralized infrastructure for cross-chain liquidity and incentives, powered by the Curve AMM. It enables efficient swaps, yield generation, and access to deep DeFi liquidity secured by the Consensus Bridge.
CrossCurve MetaLayer emerged as a logical extension of the decentralized EYWA bridge. A simple “bridge” is no longer sufficient—more advanced solutions are required for real


This layer is responsible for securely transferring liquidity between blockchains. The Consensus Bridge simultaneously uses several trusted protocols (such as Axelar, LayerZero, Wormhole), significantly reducing the risk of attacks.
This layer addresses several critical functions:
Efficient liquidity use. In traditional models, liquidity must be reserved for each blockchain pair, leading to exponential cost growth. In MetaLayer, all liquidity is concentrated in the Sonic hub-chain and shared through Curve Stable Pools. This reduces the liquidity requirement from 2N²−N to 2N, delivering up to ~49.5x efficiency gains when supporting 50 blockchains.
On-chain swaps. Curve AMM algorithms enable automatic asset exchanges based on liquidity distribution. If liquidity is lower in a certain direction, slippage increases—everything remains fair and transparent.
Secure storage. Curve pools are audited and manage over $2 billion in TVL— this represents proven security and user trust.
Decentralized governance is not just a slogan—it is the foundation of MetaLayer’s operation. All key decisions are made by DAO participant a through voting. This eliminates centralization risks. Additionally, the ve(3,3) tokenomics model allows incentives to be directed toward the most active and profitable areas. More activity means more rewards, which attracts more liquidity and makes swaps even more beneficial.
CrossCurve MetaLayer is a decentralized protocol for managing cross-chain liquidity. Unlike intent-based protocols, where core logic runs off-chain and requires complex configurations, MetaLayer stays true to DeFi principles. Anyone can become a liquidity provider and earn–no high entry barriers or reliance on centralized intermediaries.




CrossCurve Technical Roadmap
Hub Chain Migration: Transition of CrossCurve’s main liquidity layer from Fantom to Sonic for higher performance and scalability.
• New Architecture: Isolated paired pools with synthetic derivatives and Sonic-based liquidity.
• Synthetic Routing: Cross-chain swaps via Sonic liquid assets (e.g., USDC.e, scETH, scBTC).
• Efficient Swaps: Any asset from any chain can be exchanged through two pools.
• CrossCurve Incentives: Projects can incentivize veEYWA and veCRV holders for voting and liquidity attraction.
• CrossCurve Delegations: Anyone can launch a veEYWA voting aggregator, manage voting power, and earn through protocol revenue, staking boosts, bribes, and inflation rewards.
• Sonic Airdrop Rewards:
• CrossCurve won Sapphire Tier in Sonic BOOM Season 1.
• Received Sonic GEMs (~$1M).
• These will be distributed among CrossCurve liquidity providers.
• LayerZero DVN Integration:
• Provides a secure base level of trust for cross-chain swaps and messaging.
• Recommended validator network for multiple protocols.
Router v3
• Advanced Token Transfers:
• Supports transfers to arbitrary addresses.
• Integrated with top aggregators: Li.fi, Bungee, Rango.
• Collects fees for route construction.
• All transactions pass through the Consensus Bridge.
Router v4: CrossCurve as a Liquidity Aggregator
• “Router of Routers” model:
• Supports external token bridges (e.g., Circle, Tether, LayerZero OFT, Wormhole, Axelar, CCIP).
• Omnichain swap support.
• DEX Integration:
• Operates on any external DEX: Uniswap, Balancer, Velodrome, Aerodrome, etc.
• Non-EVM Expansion:
• Porting to chains like Solana, TON, Tron, Sui, Aptos, Ripple, Stellar, Cardano.
• Native Bitcoin Integration:
• Connection with Bitcoin L2 partners for native BTC liquidity.
• Governance & Sustainability:
• Launching a dedicated CrossCurve Foundation.
• Focus on decentralization, maximizing holder value, and long-term ecosystem growth.
EYWA DAO NFT is an ERC-721 NFT created when EYWA tokens are locked in the.
Key features:
Attaching assets: Each EYWA DAO NFT can have EYWA tokens, Vesting Safes, and other EYWA NFTs attached to it.
Obtaining veEYWA: The obtained veEYWA is automatically tired to the corresponding EYWA DAO NFT.
Voting in CrossCurve is more than just participation in governance; it is an effective tool for generating additional income. Your voting power (veEYWA) becomes a valuable asset capable of producing returns alongside basic staking rewards.
By locking EYWA tokens, you receive veEYWA—voting power that:
Grants the right to influence liquidity distribution between pools
CrossCurve Pools v2 is an advanced pool system designed to optimize cross-chain liquidity management within the СrossCurve MetaLayer. The system works with three primary asset types: USD-, ETH- and BTC-pegged tokens, which are issued by various projects across different networks. In the hubchain, a set of paired pools is created for each of these asset types. Each pool corresponds to a specific direction (blockchain) and functions as a bridge to that network.
The CrossCurve Token Bridge lets projects present their token on other networks by locking their assets in smart contracts and issuing the token’s derivative on other networks. Our bridge allows you to move issued derivatives between blockchains in all directions, without having to return to the original token lock network using Cross-chain Data Protocol (CDP).
Regardless of the differences among protocols, rules specifications and governance mechanics of these networks, a usage of the CrossCurve Token Bridge makes it possible for users to move assets among these chains in a reliable and secure way.
The CrossCurve Token Bridge consists of the Portal and Synthesis
Staking is the process of locking coins for a certain period, making them unavailable for trading. This mechanism supports decentralization and provides rewards to participants.
In the CrossCurve protocol, staking involves locking tokens in the DAO locker. Rewards are accrued every epoch and are tied to each user’s EYWA DAO NFT. Accrual occurs at the start of the new epoch for the previous one. In CrossCurve, the epoch length is one week, with the end of the epoch at Wednesday 24:00 UTC and the start of the epoch at Thursday 00:00 UTC.
By using the “Compound” transaction, a user can add the earned rewards to the corresponding EYWA DAO NFT, in order to add them to the principal of your position and earn compound interest.
More details on reward calculations per epoch are provided below.
Allows support for projects offering additional rewards
Creates an additional income stream beyond basic staking
Important: The more veEYWA you hold, the higher the potential earnings from voting. Projects aiming to attract liquidity to their pools offer incentives in various tokens in exchange for your support in voting.
Different projects compete for your support, offering their tokens as incentives for your votes:
Additional token payouts occur each epoch
Opportunity to receive tokens from promising projects. Selling immediately or holding onto them is your choice.
A unique CrossCurve advantage is monetizing your voting power by selling EYWA DAO NFTs:
Vote Selling: Although the veEYWA tokens themselves cannot be transferred directly, you can sell NFTs containing your voting power on the secondary.
Pricing: NFT value directly correlates with the amount of veEYWA contained and potential income from voting.
Liquidity of Locked Assets: Option to sell voting power without waiting for the lock period to end.
Given the limited issuance of veEYWA, their value could increase, enhancing the worth of your voting NFTs and creating a third revenue stream.
Track projects offering the largest rewards for voting. Analyze proposals, selecting those providing an optimal balance between:
Reward size
Project stability
Token growth potential
Or delegate this task to professionals via CrossCurve's website interface. (This feature will be available soon)
Strengthen your voting power through EYWA NFTs:
More veEYWA = more votes = higher rewards
Legendary or Infinity level NFTs can increase voting returns by up to 2.8x and 3x respectively
Regularly participate in votes to avoid idle veEYWA:
Unused votes yield no extra profits (delegate or remember to vote yourself)
Monetize your voting power by selling NFTs when necessary
Reinvest tokens received from voting into staking to leverage compound interest
Voting in CrossCurve is not merely a bureaucratic function but a tangible opportunity to gain additional income, influence the evolution of DeFi, and actively participate in a growing community.
Summation of veEYWA: The total amount of a user’s veEYWA is equal to the sum of the veEYWA of all their EYWA DAO NFTs.
Thus, EYWA DAO NFT serves as a hub for managing your locked assets and voting power in the DAO, providing flexibility and scalability in project governance.
When creating an EYWA DAO NFT in the Locker, you can lock EYWA tokens in various states When transferring to the Locker:
EYWA tokens (standard ERC-20)
Ownership is transferred to the Locker contract.
Vesting Safe contracts with direct ownership (held in the user’s wallet)
Ownership of the Vesting Safe contract is transferred to the Locker.
Vesting Safe contracts with ownership via an NFT (Vesting Safe contracts attached to an EYWA NFT)
The Vesting Safe is detached from an EYWA NFT and transferred to the Locker.
The EYWA NFT ownership is also transferred to the Locker.
ERC-20 EYWA tokens with ownership via an NFT (EYWA tokens attached to an EYWA NFT)
Tokens are detached from an EYWA NFT and transferred to the Locker.
Ownership of an EYWA NFT is also transferred to the Locker.
The Locker calculates the amount of veEYWA based on the total number of EYWA tokens locked, including both standard ERC-20 tokens and those in the Vesting Safe.
You cannot create an EYWA DAO NFT by adding an empty EYWA NFT to the Locker.
You can attach no more than 100 Vesting Safes and 100 EYWA NFTs to one EYWA DAO NFT.
You can modify an EYWA DAO NFT in several ways:
Adding additional EYWA tokens:
You can lock more EYWA tokens in any of the ways described above at the time of creating an EYWA DAO NFT.
Adding/attaching empty EYWA NFTs:
You can attach additional empty EYWA NFTs to an existing EYWA DAO NFT.
Removing/detaching EYWA NFTs:
You can detach an EYWA NFT from an EYWA DAO NFT, returning them to the user’s ownership.
Extending the lock duration of tokens:
You can extend the lock duration of already locked EYWA tokens to increase voting power.







CrossCurve is moving to Sonic
We have made a strategic decision to migrate CrossCurve's hub chain from Fantom (FTM) to Sonic. This is not just a network change - it’s a transition to a new level of speed, efficiency, and possibilities. Let's explore why Sonic is the optimal choice, what benefits it brings to users, and how this step will shape our future.
Sonic dramatically accelerates blockchain operations. The average transaction finalization time is just 720 milliseconds.
For comparison:
Ethereum — ~12 seconds
Fantom Opera — ~1-2 seconds
This makes Sonic one of the fastest EVM-compatible blockchains. In DeFi, speed is critical: minimal latency reduces arbitrage risks, improves liquidity conditions, and enhances user experience.
Sonic brings blockchain interactions closer to Web2 performance—transactions process instantly, while fees remain minimal.
Most blockchains either burn fees or direct them to network funds. Sonic takes a different approach:
Up to 90% of fees are returned to developers
Projects generate sustainable revenue without raising fees
Liquidity is redistributed to benefit everyone: users, developers, and token holders
The more activity in the network, the higher the protocol revenues and user incentives.
Sonic is an evolution of Fantom’s technology but with enhanced features.
What does this mean for projects?
Easy migration — smart contract code requires minimal changes
$120M support fund — Fantom has allocated grants to migrate dApps to Sonic
Major centralized exchanges have integrated automatic FTM → Sonic (S) swaps
We gain all the advantages of the new network without losing functionality or liquidity.
Sonic’s economy is built on the ve(3,3) concept, which incentivizes staking, liquidity, and long-term token holding.
This model has already proven successful in Curve, Solidly and Velodrome, creating a sustainable DeFi cycle.
Sonic has already attracted top players, including:
AAVE — a leading DeFi protocol managing $10B+ in assets
Curve — the largest stablecoin exchange platform
Solidly and other major DeFi projects — key players in the industry
This means liquidity and users are already migrating to Sonic, making participation in this ecosystem strategically important.
Sonic supports EVM, making it fully compatible with existing Ethereum and Fantom smart contracts.
А Sonic Gateway — a native bridge enabling secure asset transfers between Ethereum and Sonic without reliance on centralized solutions.
CrossCurve’s transition to Sonic is not just an upgrade - it’s a leap forward in technology.
What are the key benefits?
720ms transactions — faster than any other EVM blockchain
Up to 90% of fees returned to developers — projects earn more
Seamless migration with $120M support — transition risks minimized.
Top DeFi projects onboarded — Sonic’s ecosystem is growing rapidly
Each paired pool in the hubchain consists of two tokens:
Universal token - an asset from Sonic, common across all pools of the same type (xfrxUSD for USD assets, xfrxETH for ETH, and scBTC for BTC).
Synthetic derivative, backed by the original asset locked in the Consensus Bridge. This can include both single assets and Curve LP tokens.
CrossCurve Pools v2 enables asset transfers between blockchains in four stages:
Bridge from the source network: The original token is locked in the Consensus Bridge in the source network, and the Consensus Bridge then mints a synthetic token (derivative) in the Sonic network.
Exchange for the universal token: The synthetic token is exchanged for the universal token of the hubchain.
Exchange for the destination synthetic token: The universal token is exchanged for a synthetic token corresponding to the target blockchain.
Bridge to the destination network: The synthetic token is burned in the Consensus Bridge on Sonic, and the Consensus Bridge then unlocks the original token in the destination network.
The previous pool system used Curve stable pools with 8 assets, connected via liquidity provider (LP) tokens from one or more pools. CrossCurve MetaLayer introduces a fundamentally new approach — liquidity isolation, where each pool contains liquidity only for a single direction. This design delivers the following benefits:
In the previous system, incentives directed into a pool were distributed across all 8 directions, reducing their effectiveness. In paired pools, blockchains can direct incentives exclusively into their own pool, increasing liquidity in that direction and improving bridge conditions for users.
In Curve stable pools, increasing the number of tokens in a pool leads to higher slippage under imbalance. A 2-token pool shows significantly less slippage compared to an 8-token one under the same imbalance. Additionally, in the old system, a significant imbalance in one token increased slippage for all 8 directions, while in paired pools, slippage growth is confined to an affected direction only.
To minimize slippage in the previous system, equal liquidity was required across all 8 directions, which was inefficient for less active ones. Paired pools allow using smaller amounts of liquidity for lower-demand directions while maintaining the same slippage level, thus optimizing liquidity utilization.
A depeg – where an asset drops in value relative to its underlying – is a common occurrence. In multi-asset pools within a single network, a depeg can have wide-reaching consequences for all connected networks, leading to a liquidity drain across all tokens in the pool. For example, in the previous system, if one asset dropped to zero in value while each had $100,000 in liquidity, the total loss across the remaining directions could reach up to $700,000.
In CrossCurve MetaLayer’s isolated pools, a depeg from one blockchain affects only a single pool. In the same scenario, losses would be capped at $100,000. The system automatically pauses the affected direction when a depeg is detected (based on price deviation), preventing further risks. However, a pool with the synthetic derivative of the depegged token remains in the hubchain until the price stabilizes.
To move assets across Blockchains, the CrossCurve Token Bridge uses synthetic assets (s-tokens). S-tokens are created when someone needs to transfer an asset between two blockchains.
When transferring token X, the bridge uses a Lock-Mint-Burn-Unlock mechanism. The original X token is locked in the Portal smart contract on Blockchain 1. This transaction triggers an event in the bridge smart contract, which is monitored by the Consensus Bridge.
The Consensus Bridge uses multiple messaging protocols to transmit the event to Blockchain 2. Once a sufficient number of confirmations are received from messaging protocols, the synthetic token sX is minted in the destination blockchain.
When transferring a synthetic token sX, the bridge uses a Mint-Burn mechanism. The original sX token is sent to the Synthesis smart contract on Blockchain 1, triggering an event in the bridge contract.
The Consensus Bridge sends the message to Blockchain 2 through multiple messaging protocols. Once enough confirmations are gathered, a new instance of the same sX token is minted on Blockchain 2.
Let’s consider Bob transferring X token from Blockchain 1 to Blockchain 2. The process works as follows:
Bob sends a transaction to the CrossCurve Token Bridge.
The original X token is locked in the Portal smart contract on Blockchain 1.
This triggers an event in the bridge contract, which is tracked and processed by the Consensus Bridge.
The Consensus Bridge uses multiple messaging protocols to independently relay the event to Blockchain 2.
Once enough confirmations are collected, the sX token is minted in Blockchain 2.
In our example, Bob’s transaction activates the Synthesis contract in Blockchain 2, which issues the synthetic sX token, backed by the X token locked in Blockchain 1.
At any time, Bob can initiate a reverse conversion to retrieve the original X token.
Transferring tokens from one blockchain to another using the CrossCurve Token Bridge is a complex cross-chain operation. The user can track its execution in the interface in real time.
Only tokens whose smart contracts have been thoroughly audited by the CrossCurve team are added to the CrossCurve Token Bridge. The audit takes into account many characteristics of the project, and also examines the code of smart contracts for the presence of logic for moving and locking user tokens, which potentially creates a danger to user funds. Only tokens whose code complies with all security rules are allowed to be moved.
Each epoch, a fixed number of EYWA tokens (), is allocated for DAO participant rewards. This amount depends only on the total number of locked EYWA tokens in that epoch. All calculations, including the number of locked tokens and the calculated veEYWA, are performed at the end of the epoch. The allocated rewards are then distributed among participants proportionally to their share of veEYWA.
Calculating the ratio of all locked EYWA tokens in this epoch to the total possible volume of EYWA tokens (1,000,000,000):
If is less than 0.14, then is calculated as:
, where
Inflation - the emission amount in the calculation epoch.
If is greater than or equal to 0.14, then is calculated as:
, where
Inflation - the emission amount in the calculation epoch.
All numerical coefficients indicated in the formulas are current at the time of DAO launch. They can be changed by DAO participants via voting.
For convenience, we have prepared tables with results grouped by different levels of locked token amounts.
After determining the total amount for all users (), it is distributed among DAO participants proportionally to the amount of veEYWA each participants holds.
, where
- the user’s veEYWA,
- the total veEYWA of all users,
- the total reward allocated to all participants.
▪️ ✅New and pools, as well as adding new chains
Adding pools with Ethereum and Bitcoin, support of the Linea, Mantle, Blast, and Taiko chains.
▪️ ✅
A unique program for liquidity providers within which users will be rewarded with rEYWA tokens. These tokens can then be exchanged for $EYWA 1:1 after the TGE.
▪️ ✅The first cross-chain listing on
Listing of a project on the , which will make that token available for trading at once in all the networks included into CrossCurve.
▪️ ✅Two $EYWA sale community rounds
An exclusive opportunity for the EYWA community (alpha-testers and anyone Airdrop-eligible) and our key partners — Curve Finance and Alphamind — to obtain $EYWA tokens prior to the listing.
▪️ ✅Activating the NFTs’ utility
The transfer of EYWA NFTs into the Arbitrum network, activation of the merge function of the NFT, the ability to claim the Airdrop after the TGE, and listing on popular marketplaces.
▪️ ✅TGE
Token generation, the start of the unlock period, and the preparation for CEX listing.
▪️ ✅CEX listing
Adding the $EYWA token to centralized exchanges in December 2024.
▪️ ✅Launch of the EYWA DAO
Transferring the control over all of the EYWA smart-contracts to the DAO community. Creating a marketplace of incentives for the EYWA DAO community, and the launch of veTokenomics. Stimulating the demand for $EYWA from Web3 projects and liquidity providers.
▪️ ✅Multiple Incentives in the EYWA DAO
Increasing the income in several pools via a collaboration with Curve Finance. Governing the revenue via DAO voting.
▪️ ✅Adapting the TG Mini App for onchain-education.
▪️ Upgrading Hubchain to Sonic
Lowering gas fees, increasing transaction speed, and strengthening of security by connecting to the Consensus Bridge.
▪️ Connecting partner bridges & tokens to CrossCurve
Adding new tokens from large partner projects for swapping on CrossCurve.
✅Launching and updating websites & PR campaign in February.
✅Launching CrossCurve DEX based on the aggregation of Curve pools and Eywa Oracle Network in March.
✅Implementing a point system and new tasks in EYWA Adventure Quest.
✅Launching CrossCurve app, using Curve liquidity pools in March.
We present the new improved edition of CrossCurve tokenomics, developed in accordance with the recommendations of experts, auditors and advisors.
🔗 Full version of CrossCurve tokenomics is available in this spreadsheet
Listing price: $0,07 Fully diluted valuation: $70 000 000 Market cap on TGE: $3 023 740 IMC (without liquidity): $921 539
After listing, the total circulating number of the Eywa tokens will be 43 196 286 (4,32% of the total supply). This figure represents the sum of the tokens unlocked on the community round, market-making tokens, airdrop, treasury and KOL tokens.
The TGE stage includes the following steps:
The Eywa token will be deployed in chain;
The entire EYWA emission (1 billion tokens) will be issued and then transferred to the chain using the CrossCurve Token Bridge.
The vesting contracts will be deployed in chain.
EYWA is an omnichain token and can be moved to ,
The CrossCurve tokenomics outline various user categories, each with different lockup periods. After the TGE, all users will receive their personalized safes with vested tokens.
A vesting period is a time interval during which tokens are unlocked according to a previously approved schedule. The tokens’ unlock logic is programmed into smart contracts and cannot be changed.
A vesting mechanism aims to mitigate pressure on a token market price, reduce the likelihood of speculation, protect the interests of token holders, and positively influence the long-term project development.
Details on vesting periods and the unlock scheme are available in the CrossCurve .
Limited movement. Allocations above 1.5 million tokens can only transfer their vesting tokens to whitelisted addresses, facilitating an OTC market.
Allocations of smaller size, including all Airdrops rounds and Community round participants can move their tokens but ONLY by using . This feature will be available after the migrates to Arbitrum.
In simple terms, this means that these tokens can be tied to Eywa NFTs and sold on an at any time before the lock-in period ends.
Opportunity to use vesting tokens for staking.
Eywa vesting token holders can stake their tokens before the end of the vesting period and receive staking/farming rewards.
Opportunity to participate in the CrossCurve DAO to receive veEYWA votes.
Note: Any changes in the accruals during validators’ rounds will be updated .
CrossCurve offers two distinct types of pools, each with unique features and earning opportunities.
Stable pools are designed for assets whose prices are pegged to each other:
Examples: Stablecoin pairs, such as USDT/USDC
Derivative Assets: Pairs like wstETH/rETH are also considered stable since their relative prices do not fluctuate significantly
Goal: Maintain an exchange rate of 1:1 between assets as accurately as possible
Features: Minimal slippage and stable exchange prices due to a specialized AMM formula
Stable pools are optimized for trading correlated assets with minimal losses and slippage, making them attractive to conservative investors.
Volatility pools are intended for pairs of assets with fluctuating prices:
Examples: USDT/EYWA, ETH/BTC and other uncorrelated assets
Formation: Created by combining heterogeneous assets
Protection: Utilize Curve's unique mechanism to mitigate impermanent loss
Features: Higher risk but potentially higher returns
Volatility pools are suitable for investors willing to accept higher risks in exchange for potentially higher returns.
CrossCurve offers two modes for adding/removing liquidity:
Allows adding or removing funds with a single asset
Simplifies the process for beginners
Automatically handles all necessary conversions and transactions
Designed for adding large sums
Requires balanced addition of assets to optimize yield
Minimizes slippage losses
When working with liquidity pools, it's essential to understand the concept of balance:
An ideally balanced pool has an equal percentage distribution of all assets
For instance, in a xCRVUSDC pool with six s-tokens, the optimal share for each asset is 16.6% of the total TVL
Adding an underrepresented asset (share <16.6%) earns an additional bonus
Adding an overrepresented asset (share >16.6%) results in losses
The primary income source for liquidity providers is the trading fees from swaps occurring within the pool:
Fees are automatically distributed among all liquidity providers
The amount of fees received is proportional to your pool share
In addition to trading fees, liquidity providers may receive extra incentives:
EYWA inflation allocated by CrossCurve DAO voting as an incentive to attract liquidity
Other tokens added by external projects to attract liquidity
Increased rewards for veEYWA holders (vote-escrowed EYWA)
Points for participating in external project programs
Obtaining higher yields by placing funds into CrossCurve pools through strategies within “Curve Wars” protocols, such as Convex or StakeDAO
CrossCurve's unique advantage is its ability to manage liquidity across different blockchains:
Liquidity providers can add and withdraw liquidity from all available networks
Liquidity providers can swap LP tokens across networks without impermanent loss
The ability to quickly and cost-effectively move funds in search of higher yields
To maximize yields when providing liquidity, it's recommended to:
Analyze pool conditions before adding liquidity
Select the optimal mode:
Easy Mode for small amounts and beginners
Providing liquidity on CrossCurve is a powerful earning tool in DeFi. The platform combines Curve Finance's proven reliability with CrossCurve's innovative cross-chain technologies, ensuring user security, convenience, and potentially high returns.
It’s crucial to remember that liquidity provision always entails certain risks; thus, it’s advisable to carefully study pool mechanisms and yield optimization strategies before making significant investments.
Routing provides a convenient graphical representation of a cross-chain transaction, showing all the transitions and fees involved step-by-step:
Routing Details Legend
- Adding token to the pool
- Removing token from the pool
- Burning of synthetic token
- Receiving asset from the pool (LP or token obtained in exchange)
- Cross-network transition using lock/receive or burn/unlock mechanics
- Token exchange within the pool
- Unwrap the native token
There are situations where a cross-chain operation may be interrupted:
The operation is interrupted based on the Slippage condition. If, during the transaction execution in one of the pools, the slippage exceeds the upper limit set by the user, the transaction will be interrupted, and the intermediate tokens will be credited to the user's address on the network where the interruption occurred.
The operation is interrupted because the cross-chain call cannot be executed. If the infrastructure facilitating cross-chain interaction fails to execute the cross-chain call, the operation will be interrupted.
The transaction interruption will be displayed as a message in the Transaction history, where the user will be provided with actions to handle the situation.
"Curve Knowledge Database" is your comprehensive resource for all things related to Curve Finance.
🥽Dive into expert insights on Curve's unique AMM system, liquidity pools, staking strategies, and yield optimization techniques. Whether you're a beginner seeking basics or an advanced user exploring in-depth mechanics, this knowledge base is equipped with tutorials, FAQs, analytics, and community wisdom to guide your decentralized finance journey on Curve. Stay informed, stay ahead.
Balanced mode for larger sums and experienced users
Monitor pool balance when adding or removing liquidity to earn bonuses rather than incur penalties due to pool imbalances
Combine with EYWA locking to obtain additional rewards through yield boosts
Participate in voting for liquidity distribution between polls and vote for your pool (if beneficial, considering other opportunities for selling votes)














✅Launching new quest tasks on the website in March.
✅Launching the Ambassador Program.
✅Launching the Early farming program.
✅Undergoing a comprehensive third-party audit to enhance Consensus bridge security
✅Expanding the KOL list for TGE & new partnerships
✅Launching Season 2 of the Airdrop
✅Introducing the long-term on-chain Ambassador Program
✅Conducting Eywa token TGE on Arbitrum and token sales on launchpads.
Migrating to Eywa Consensus Bridge.
✅Conducting the first cross-chain listing of a token
✅Conducting a Community Round.
✅Paying bribes to Curve and Convex via Stake DAO and Votium to attract incentives to the main pools.
✅Launching EYWA DAO for EYWA token's main utility.
✅Offering bond purchases, based on Bond Protocol.
✅Migrating the EYWA NFT collection to Arbitrum, activating EYWA NFT functions - container, merge, vote boosting in EYWA DAO, and getting tokens locked in NFTs.
✅Launching a vote-boosted farming program.
Creating the EYWA DAO bribery market.
✅Integrating Convex, StakeDAO, and Yearn (cvxEYWA, sdEYWA, yEYWA markets) - launching staking for Eywa token.
Integrating into cross-chain bridge aggregators: Rubik, Li.Fi, etc.
✅Receiving CEX confirmation for primary listing
Uniswap V2/V3 integration for cross-chain token listings












The CrossCurve team will send the Eywa token emission to the vesting contracts in accordance with the project’s tokenomics.
Token distribution begins after Listing date in a special section on app.crosscurve.fi which will become available after the TGE. On TGE, users will be able to connect their wallets and access their personal vesting safes, linked to their addresses. During the vesting period, Eywa tokens are unlocked according to the scheme defined in tokenomics, and owners can transfer the unlocked tokens to their wallets.
The Listing date will occur no later than 14 days after TGE.

To start working in the CrossCurve application, go to the Liquidity section, in the top right corner click “Connect wallet”, select a suitable wallet from the list and confirm the connection, making sure that you are on the original page https://app.crosscurve.fi/liquidity.
After successfully connecting, in the Choose pool window, select the pool or asset you are interested in for working with liquidity.
Once you have chosen the necessary asset, the interface will display the TVL in the selected pool, as well as a link to the original pool of the selected asset on , your Wallet Balance showing the amount of the asset, and the Estimated APR for Farming in the selected pool.
The next step is to select the operation to be performed with the asset ( or ) and the method of execution, or .
For convenience, a quick link to add the token to the wallet via the contract address has been added for correct balance display. By clicking on the “+”, a request will pop up to add a custom token. After signing, it will be displayed in the wallet.
The EYWA NFT collection can be found on the Aurora and Arbitrum blockchains.
You can view your EYWA NFTs right on our website in the NFT->Gallery tab.
The Gallery/Bridge tab allows you to see all the connected wallet’s NFTs on the Aurora chain available for bridging to the Arbitrum chain.
The Gallery/Merge tab allows you to see all of the connected wallet’s NFTs on the Arbitrum chain available for rarity increase via merging.
CrossCurve DAO — is a democratic, transparent, and decentralized organization that makes strategic decisions, engages participants, and incentivizes their contributions.
The goal of CrossCurve DAO is to create long-term incentives for attracting sustainable cross-chain liquidity, as well as to accumulate and manage the protocol’s own liquidity to ensure better conditions for cross-chain swaps in the market.
DAO governance is based on locking the EYWA governance token into veEYWA, which grants voting power. This voting power allows veEYWA holders to participate in decision-making, receive incentives, and earn income from EYWA protocols.
Here is the pool , and the of supported tokens.
1. To start, go to the Curve Finance website via the, or go to the Pools tab and enter the name of the pool you wish to find (avDAI/avUSDC/avUSDT) in the search bar. You need to select the network in which the liquidity pool is located where you want to deposit your tokens (liquidity). For this example, the Avalanche network will be used.
The operation is interrupted based on the Slippage condition.
If an interruption occurs in one of the pools in the cross-chain transaction chain due to the slippage condition, the tokens that were input into the pool will be credited to the sender's account, and the user will be prompted to continue the operation.
By providing liquidity in CrossCurve pools you can earn rewards in EYWA and/or CRV.
Migrating the hubchain to Sonic is a major system upgrade affecting the protocol’s architecture, mechanics, and economy. The principles of working with liquidity are changing, system resilience is increasing, and new earning opportunities are opening up for CrossCurve users. Below are the key stages of this transition:
Pools based on a new architecture—isolated pair pools—are being launched on Sonic. Previously, large multichain pools were used, combining up to 8 blockchains with synthetic derivatives. Now, each pool includes only the liquidity of one isolated blockchain and the hubchain – in this case, the liquid tokens of the Sonic blockchain.
This approach enhances the system’s overall resilience and reduces imbalance risks. Individually, the pools will be less liquid, but the overall architecture will provide greater flexibility, resilience, and potentially higher returns for liquidity providers.
Curve pools are based on a specialized AMM formula for trading stablecoins with minimal slippage and stable prices. Differing from the standard AMM formula x * y = k, Curve applies a modification focusing on assets with similar prices, providing effective pricing and liquidity for closely correlated tokens. Pools are adapted to the market by adjusting the asset weights, allowing them to maintain stable exchange prices even with changing market volatility. Therefore, it is necessary to pay attention to the liquidity balance of each stablecoin in the Pool Details tab. Go to the original liquidity pool on Curve you are working with, and assess its balance. For example, let's consider the xCRVUSDC pool.
The xCRVUSDC pool consists of six s-tokens, so the pool will be balanced if the share of each asset in the pool constitutes 100/6 = 16.6% of the total TVL of the pool.
Merge interface description in the Arbitrum chain
After successfully connecting your wallet in the «Gallery/Merge» tab, the gallery will show all the NFTs stored in the connected wallet, sorted by .
For your convenience, use the NFT rarity filter to choose the rarity category you want to level up.
Select the necessary number of NFTs for merging and rarity increase and click «Merge»:
CrossCurve (ex EYWA) founders
Boris Povar holds a degree in software technology and IT administration, and is a mathematician. Boris started to work in IT since 2009 and become a serial entrepreneur via launching his IT outsourcing company, and crypto start-ups. Boris has both great theoretical and practical experiences in mining, cloud mining, crypto trading, investing and crypto asset management. As an initial creator of the Blockchain Laboratory dedicated to researching the DeFi market, Boris comprises the complex deep knowledge and experience in DeFi and its corresponding matters.
We are initiating a voting process in the Curve DAO to get whitelisted and connect the pools to protocol reward distribution. This will allow us to activate CRV incentives for our pools and increase yields for our liquidity providers. Since the voting takes about two weeks, we are starting the process in advance to launch reward distribution as quickly as possible after migrating our hubchain.
After deployment and basic setup, the Sonic pools will be connected to our routing system. At this stage, swaps through the new pools in Sonic will become available to CrossCurve users. To ensure a seamless transition, Sonic and Fantom pools will operate in parallel, allowing liquidity to flow between them without interrupting system functionality.
After launching the pools and connecting them to the infrastructure, we will activate incentives from CrossCurve DAO – our first step in attracting liquidity to the new Sonic pools. External projects will be able to offer rewards to CrossCurve DAO participants in exchange for votes on specific liquidity pools, allowing users to start earning right away.
As Sapphire-tier winners in the Sonic Boom program, we possess special airdrop points called Gems. These are distributed among applications based on product metrics and activity. We will direct all of them toward incentivizing liquidity in our pools in the form of the cmGEMS1 token, using it as a reward distribution mechanism within the protocol.
WE ARE HERE
As incentives are activated on Sonic pools, they will simultaneously be disabled on Fantom. However, CRV rewards will continue to be distributed for some time after deactivation due to the mechanics of Curve.
After most of the liquidity has been migrated to Sonic, Fantom pools will be disconnected from the routing system. Swaps through them will no longer be possible; the pools will remain accessible for withdrawals only. It is especially important for CrossCurve users to move their assets before this stage to avoid high slippage, as the majority of liquidity will have already been relocated.
At this stage, the pools will start generating Sonic Points and Rings, allowing liquidity providers to participate in additional reward programs, including all future airdrops. Thanks to the new pool architecture, half of the liquidity will be concentrated in Sonic blockchain assets, enabling our users to earn even more incentives
After completing the Curve vote and configuring campaigns on Votemarket, we will activate the reward distribution in $EYWA and $CRV tokens – thus completing the migration of our hubchain to Sonic and fully launching most of the economic incentives in the new pools.
15 years experience in BD, VC & Corporate. Harvard Business School Executive Education. MBA from WBS (UK). Founder of the Crypto Executives community (2000+ c-level executives).
Our team consists of 35+ members.
We work remotely. The founders live in Turkey and UAE. The CrossCurve team is distributed all over the world: Turkey, UAE, Ukraine, Mexico, Russia, Israel, Latvia and etc.








Liquidity provision on CrossCurve offers the chance to contribute to the market stability of cross-chain assets. By staking tokens in liquidity pools like EYWAUSDT or CrossCurve frxUSD, providers earn trading fees from swaps occurring within the pool. This process not only provides a potential income stream through fees and rewards but also plays a crucial role in facilitating smooth cross-chain transactions.
Savvy investors can leverage CrossCurve's advanced AMM algorithms to balance risk and return, optimizing their positions in a multi-token ecosystem. Always consider the associated risks and conduct due diligence before participating.
👇 Learn how to deposit and withdraw liquidity from CrossCurve pools in the sections below. Use the sidebar for easy navigation between sections.
DepositWithdrawCurve Knowledge DatabaseLocking EYWA provides you with the following benefits:
Staking income
Voting rights and participation in DAO decision-making
Incentive earnings when voting for pools
Increased rewards for providing liquidity
A share of the platform’s fee revenue
veEYWA stands for vote-escrowed EYWA. Users can lock their EYWA tokens for a maximum of 3 years, in exchange for veEYWA. The amount of veEYWA decreases linearly as the chosen lock duration elapses. veEYWA cannot be transferred directly, but can be transferred within an EYWA DAO NFT. The longer you lock, the more veEYWA you receive. For details, please see the lock formula, but the simple explanation is:
1 EYWA, locked for 3 years = 1 veEYWA
1 EYWA, locked for 2 years = 0.66(6) veEYWA
1 EYWA, locked for 1.5 years = 0.5 veEYWA
1 EYWA, locked for 1 year = 0.33(3) veEYWA
The longer you lock your EYWA, the greater your voting power (expressed in veEYWA) and the higher the boost you can achieve.
Owning an EYWA NFT can affect the amount of veEYWA you receive and, therefore, your voting power. An NFT’s rarity is determined by two parameters - MV (multiplier for veEYWA), a multiplier applied to the veEYWA you receive; as well as CT (Capacity per NFT), the maximum number of EYWA tokens affected by the NFT’s influence. Check the table below for the characteristics of each rarity level:
common
1.006
500
uncommon
1.036
3 000
rare
1.3
25 000
legendary
2.8
EYWA NFTs enhance your DAO voting power, increase returns from staking, incentives, and fees, and allow trading of locked tokens. They also attract investors due to their rarity and functionality.
Here are some ways EYWA tokens benefit different types of users:
For veEYWA holders - those who have locked their tokens to gain voting power:
Boosts voting power when making DAO decisions
Boosts the voting power that can be exchanged for incentives (to distribute EYWA inflation across CrossCurve pool gauges)
Boosts staking income for veEYWA holders
Boosts the voting power used for distributing $EYWA in CrossCurve pools
Boosts income from distributing the protocol’s fee revenue among veEYWA holders
Staking income is the reward for long-term holding and locking of EYWA tokens. The longer and larger the locked amount, the higher your staking rewards, which are credited at the end of each epoch.
Also, staking yield depends on the total volume of locked EYWA: the more tokens locked, the lower the yield.
You can view the detailed calculations at the following link.
Using EYWA DAO NFT further increases your staking earnings.
CrossCurve DAO functions include:
Managing protocol contracts: bridges, new networks, contract deployments, fees, and permissions.
Managing the DAO treasury: inflation (amount and rate), incentives for community development, expenses to attract customers and partners, emission to bonds, gauges, and grants.
All of these functions are carried out through voting.
CrossCurve DAO voting is divided into three main categories. Core voting affects the calculation of the voting coefficient for distributing staking rewards.
Core voting addresses:
Changes/additions to DAO, CrossCurve, and EYWA functionality;
Incentives;
Inflation and directives;
Bonds;
Grants;
Gauges.
Other voting topics:
Incentive proposals;
Incentive directions;
Gauge listings.
Miscellaneous votings:
Votings not included in the categories above.
CrossCurve DAO allows certain pools to receive additional rewards from $EYWA token emissions.
When $EYWA emissions are allocated to a pool, the interface displays a range of possible APR that users can earn by staking their LP position.
The final APR boost depends on the user’s voting power (formed by locking veEYWA) and the ratio of your liquidity to the total liquidity, taking into account other participants’ boosts in a specific pool. A maximum boost can increase your yield by up to 2.5 times.
Thus, holding veEYWA allows you to achieve higher returns when providing liquidity. Using EYWA DAO NFT further increases your yield boost in these pools.
Locking EYWA tokens provides unique opportunities for additional income through receiving incentives for voting on certain pools. By voting, veEYWA holders determine the distribution of liquidity and rewards among CrossCurve pools. Projects seeking to attract liquidity offer veEYWA holders incentives (various tokens) in exchange for votes in their favor.
Locking EYWA turns voting rights into a source of income: veEYWA holders choose the most profitable offers and receive rewards in tokens, cryptocurrencies, or other forms of income from the projects. The higher your veEYWA balance, the more profit opportunities you have.
Using EYWA DAO NFT further increases your earnings when voting for pools.
On the pool page, connect your wallet to the site by clicking on "Connect Wallet".
3. Choose the installed wallet (or use Wallet Connect) and confirm the connection, making sure you are on the original page https://curve.finance.
4. On the pool page, interaction happens through the application highlighted in the screenshot; look for the Deposit tab.
5. In the Pool Details tab, pay attention to which tokens (DAI.e, USDC.e, and USDT.e stablecoins) are part of the pool.
The avDAI/avUSDC/avUSDT pool consists of three stablecoins; accordingly, the pool will be balanced if the share of each asset in the pool constitutes 100/3 = 33.3% of the total TVL of the pool. (more details here)
6. We will demonstrate a balanced method of adding liquidity to the pool – you can use multiple assets so that your operation brings the pool into a balanced state. This method should be applied to avoid penalties and earn additional profit from Curve in cases where you work with large amounts relative to the total TVL of the pool, or when the pool is close to perfect balance.
For balanced funding, in the Deposit tab, select "Add all coins in a balanced proportion" and the system will automatically distribute them in equal proportion. Indicating the amount, confirm spending (click on Approve Spending). In the Edit tab, you can edit the amount of funds available for spending (by default – unlimited)
7. After successful confirmation, you will see a green button labeled Spending Approved. Then, click on Deposit. After confirming the transaction, you will see a green Deposit Complete button, and the balance of av3CRV LP tokens will be displayed in the Your Details tab.
Go to Transaction History and click Details next to the interrupted transaction.
To continue a transaction that failed due to a slippage error, click Continue operation.
After clicking the Continue operation button, the application will switch to the Continue operation mode. The difference between the Continue operation mode and Normal mode is that in the Continue operation mode, the User will be sent native tokens (if the User’s wallet doesn’t have the chain’s native token for completing the transaction) to pay the gas fee for continuing the transaction in the chain where the interruption occurred.
After pressing the button, the user will be taken to the Swap interface with preselected assets:
In the top FROM field, the "intermediate" tokens that were credited to the user's wallet on the network where the operation was interrupted will be selected.
In the bottom TO field, the desired asset that the user initially wanted to receive but the operation was interrupted will be selected.
Sequence of actions in the Continue operation mode window:
Review transaction details such as Slippage and exchange rate in the dropdown menu.
Give permission for the application to interact with the asset
Sign transaction.
If a User changes values in the Source field, the application will switch to the standard Swap mode and no native asset will be transferred to the user's account to pay for the gas.
Total Slippage is the total effective slippage applied across all networks where a swap occurred during a cross-chain transaction.
It is calculated as the sum of slippage percentages for each individual network involved in the transaction (details here).
The user will have one free attempt to continue the transaction with new fees and Slippage conditions. If for some reason you can not continue the operation, сontact support on Telegram / Discord and our support team will help you.
After specifying the LP amount, click Approve EYWAUSDT and confirm spending of LP tokens by singing the transaction in your wallet.
Then click Stake, and sign the transaction in your wallet.
After the transaction is successfully completed, the balance of staked LP tokens will be displayed on the page of the pool where you locked the funds in the Staked section.
Unstake LP tokens by clicking Unstake.
After specifying the LP amount click Unstake and sign the transaction in the wallet.
For farming rewards in EYWA and CRV simultaneously, click Claim in all pools
Confirm the transaction in Your wallet.
Also you can go to the Merkl dashboard by clicking the link and claim the rewards manually
After successfully connecting your wallet, go to the Claim section and follow the instructions on the Merkl website.

If you add one asset to the pool, the share of which is less than 16.6%, you will receive an additional bonus for balancing the pool.
If you add one asset to the pool, the share of which is greater than 16.6%, you will receive a penalty in the form of slippage because this operation worsens the pool balance.
If you withdraw one asset from the pool, the share of which is less than 16.6%, you will receive a penalty in the form of slippage because this operation worsens the pool balance.
If you withdraw one asset from the pool, the share of which is greater than 16.6%, you will receive a bonus because this operation balances the pool.
It should be noted that this example is not a financial strategy, and the imbalanced Easy mode is not always profitable (for example, if the pool is balanced) and also depends on the liquidity volume you are working with: the higher your volume relative to the total TVL of the pool, the more likely it is that the imbalanced method will be disadvantageous and you should use the Balanced mode. To avoid high losses of funds, always consider these factors and the condition of the pool before making a decision about the operation.
Here is an example, how the volume of liquidity you work with can affect the final result when performing the operation.
Then, select a new image for the resulting NFT and click «Accept merge»:
After selecting the new image, you will see information about the NFTs you’re merging and the total number of EYWA contained within them. To merge them, click «Merge» and confirm in the wallet:
After the successful merge, you will get a notification along with a link to the hash of the transaction:



Every three months (every 12 epochs), the project may initiate a vote to change the parameters of token emission distribution from the CrossCurve Treasure.
During this voting, the following parameters are determined:
The amount of emission per epoch: the total number of EYWA tokens allocated for the project’s development.
The percentage allocated to pool rewards (Pools incentives).
The percentage allocated to bond creation (Bonds incentives).
The percentage allocated to grants (Grants incentives).
The percentage allocated to attract external rewards to project pools (Bribes incentives).
Voting frequency: Once a voting is initiated, the next one can only occur after three months.
Parameters for voting: All five parameters must be proposed for the voting:
Emission amount per epoch.
% for Pool incentives.
% for Bond incentives.
% for Grant incentives.
Restrictions:
The sum of percentages for parameters 2-5 must total exactly 100%.
The emission per epoch cannot exceed the average emission since the DAO’s launch by more than 25%.
Reducing emission is not restricted and can be lowered to 0, if DAO participants support it.
Emission per epoch: 1 262 295 EYWA tokens.
38% — Pool incentives.
25% — Bond incentives.
Determining the total emission volume A certain emission amount E is allocated from the EYWA Treasure (for example, the initial 1 262 295 EYWA tokens or another value approved by the DAO).
Calculating staking rewards: The amount of staking rewards S is calculated.
Calculating token volumes for incentives After deducting the staking rewards, the remaining amount is distributed as follows:
Note:
The sum of , ,and coefficients must be 100%.
All veEYWA holders can participate in weekly (every epoch) voting to distribute Pool incentives among the pools.
Pool incentives are EYWA tokens, allocated from the CrossCurve Treasury each epoch to attract liquidity providers to the project. DAO participants vote on how this amount is distributed among the pools.
The more votes directed to a pool where a provider’s liquidity is located, the higher their reward in the next epoch.
Only those pools connected to the CrossCurve project are eligible for Pool incentives distribution:
Pools created by the project before the DAO launch.
Pools added via a DAO vote.
Any DAO participant can initiate a vote to add a new pool.
To include a pool in the list, the proposal must receive more than 50% of the DAO votes.
Voting takes place on a separate page in the DAO section. To participate, a user must:
Distribute all 100% of their votes among the available pools.
Press the "Vote" button to confirm their voting choice.
Before the end of the current epoch, a user can cancel their votes and vote again.
Vote Counting Process:
At the start of a new epoch, all veEYWA votes cast for pools in the previous epoch are counted. The percentages allocated by participants are converted into a specific number of EYWA tokens directed to each pool.
Formula for Incentive Distribution:
where:
— the number of EYWA tokens allocated to pool X.
— the total EYWA token amount allocated to all pools in the current epoch
— the amount of veEYWA votes cast for pool X.
— the amount of veEYWA votes cast for pool i out of all n pools
Thus, the number of EYWA tokens allocated to a pool depends on the proportion of veEYWA votes that pool received relative to all votes.
At this stage, all incentives allocated each epoch to attract liquidity providers to the project’s pools are distributed via service.
CrossCurve Treasure → Pools incentives → Gauge → Angle Merkl → Liquidity Providers
Liquidity providers can claim their rewards:
Through the project’s pool interface.
Through the service interface.
If a liquidity provider is also a DAO participant, they receive increased rewards through a boost coefficient B.
where:
— the user’s boost coefficient (cannot exceed 2.5)
D — the total sum of all deposits in the pool (in USD)
d — the user’s deposit amount in the pool (USD).
V — the total veEYWA of all users.
v — the user’s veEYWA amount.
A maximum boost of B=2.5 does not mean the reward is simply increased by 2.5 times. The total is divided among all liquidity providers taking into account their individual boost coefficient B.
Where:
— the user’s reward
— the total amount of tokens allocated as liquidity rewards
— the user’s boost coefficient
— the user’s deposit size (USD).
— the boost coefficient of user i.
— the deposit size of user i (USD).
Maximum boost coefficient: 2.5.
Rewards are distributed proportionally, taking into account each user’s deposit and boost coefficient.
This system incentivizes DAO participants to provide liquidity, increasing their returns thanks to holding veEYWA.
Staking is the simplest way to earn passive income in CrossCurve. All you need to do is lock EYWA tokens (instructions available here), which automatically makes you a member of our DAO and enables you to receive rewards every epoch. You can boost your earnings through additional mechanics like longer lock durations, using NFTs, and participating in votes.
Each epoch, a portion of EYWA tokens from the DAO Treasury is allocated to incentivize protocol activity. Most of these tokens go to rewarding DAO participants.
To receive these rewards, you must lock EYWA tokens in the DAO Locker. Once locked, you receive an NFT that records your voting power — veEYWA. The more veEYWA you hold, the larger your share of the rewards.
Each epoch runs from Thursday 00:00 UTC to Wednesday 24:00 UTC. At the start of each new epoch, rewards from the previous one are .
Formulas:
veEYWA = ((EYWA amount × lock period in weeks) ÷ 156
User share = your veEYWA ÷ total veEYWA in DAO
Reward = User share × total reward pool (EYWA)
Weekly Return Rate (WRR) = Reward ÷ locked EYWA amount
For example, if you lock 156 EYWA for 1 week, then you will get:
1 veEYWA
If total veEYWA in the DAO is 1 000, and the reward pool is 1 000 EYWA, then your reward is:
0.1% of the pool = 1 EYWA
Weekly return rate (WRR): 0.64%
Your income depends directly on your share of veEYWA. To increase it, you can:
Lock more EYWA tokens
Extend your lock duration
Use EYWA NFT with a
These methods can be combined. Here are strategy examples:
Locking 1560 EYWA for 1 week will get you:
10 veEYWA (10 times more)
If total veEYWA in DAO is 1009, then your share is:
0.99% of the pool = 9.9 EYWA (9.9 times more)
Weekly return rate (WRR): 0.63% (almost no change)
Locking 156 EYWA for 3 years (156 weeks) will get you:
156 veEYWA (156 times more than when locking for 1 week)
If total veEYWA in DAO is 1 155, and the reward pool equals to 1 000 EYWA, then your share is:
13.5% of the pool = 135 EYWA (135 times more)
Weekly return rate (WRR): 86.5% (135 times higher)
Locking for a longer period significantly boosts both rewards and returns — the most efficient strategy without extra spending.
Locking 156 EYWA for 1 week and using NFT with the x3 multiplier will get you:
3 veEYWA (3 times more than without an NFT)
If total veEYWA in DAO is 1002, and the reward pool equals to 1 000 EYWA, then your share is:
0.29% of the pool = 2.9 EYWA (2.9 times more)
Weekly return rate (WRR): 1.9% (approximately 3 times higher)
NFTs give an instant boost — same amount and duration, but 3x higher veEYWA and rewards. This is a great option to multiply your profits.
Locking 156 EYWA for 156 weeks and applying NFT x3 will get you:
468 veEYWA (468 times more)
If total veEYWA in DAO is 1467, and the reward pool equals to 1 000 EYWA, then your share is:
31.9% of the pool = 319 EYWA (319 times more)
Weekly return rate (WRR): 204.5% (319 times higher)
Combining max lock duration and NFT multiplier creates a compounding effect, giving a 468x increase in veEYWA compared to the base case. This leads to significant return and relative profit growth.
In addition to the steps you can take to maximize your APR, it’s important to consider “external” conditions. In the section “How to increase staking income,” we looked at examples where the veEYWA volume of other DAO participants was static. But in reality, this figure is constantly changing. One important point: how other participants lock their EYWA also affects your final yield.
Let’s consider a few simple scenarios with two DAO participants. Suppose that in the previous epoch, only two users participated in the DAO:
Scenario 1: both locked 75 000 EYWA for the maximum term (3 years)
veEYWA of participant A = 75 000
veEYWA of participant B = 75 000
Total veEYWA = 150 000
Shares are equal — both participants receive 50% of the rewards
Scenario 2: both have 75 000 EYWA, but:
Participant A locks for 3 years → 75 000 veEYWA
Participant B locks for 1 year → 25 000 veEYWA
Total veEYWA = 100 000
Participant A receives 75% of all rewards
Based on the the total reward pool for the week (epoch) is 13 190.73 EYWA, therefore:
Reward A: (75 000 / 100 000) × 13 190.73 = 9 892.5 EYWA
Reward B: (25 000 / 100 000) × 13 190.73 = 3 297.5 EYWA
Weekly Return Rate (WRR):
WRR A = (9 892.5 ÷ 75 000) × 100% = 13.19%
WRR B = (3 297.5 ÷ 75 000) × 100% = 4.37%
APY calculation:
APY A = ((1 + 13.19% ÷ 100%)^52 – 1) × 100% ≈ 62 700%
APY B = ((1 + 4.37% ÷ 100%)^52 – 1) × 100% ≈ 824%
To receive staking rewards each epoch, you must press the “Compound” button. This action adds the accrued reward to the lock amount.
Increasing the lock amount raises your veEYWA share and, accordingly, your reward in the next epoch. The yield displayed on the locker page (APY) is shown assuming regular use of Compound — based on the principle of bank compound interest.
If you do not press Compound, your yield will be lower than what is shown in the interface. Therefore, to earn income that matches the displayed APY, you must manually add the reward to the lock each epoch.
Lock EYWA for the maximum term
Use NFTs with a high multiplier
Press “Compound” each epoch
Participate in incentive voting
Staking in CrossCurve is more than just passive income. It includes many mechanics that allow you to earn returns far beyond traditional staking.
You’re not just earning — you’re helping shape the CrossCurve ecosystem and receiving real rewards for it.
As part of Sonic’s Airdrop Season 2, CrossCurve has launched the CrossCurve MetaPoints program to reward active users of CrossCurve.
Participants:
Users who provide liquidity to participating pools* in the Farms tab by staking LP tokens in the CrossCurve app
Users swapping cross-chain via the Trade interface (as long the the swap’s route passes through the )
Rewards:
Participants receive MetaPoints. Also, their activity helps CrossCurve receive more , which will be swapped to $S tokens at the end of . All of the received $S tokens will be distributed among all the participants who got enough MetaPoints to receive at least one $S
Pool marking:
Pools participating* in the MetaPoints program will be marked with a special symbol .
Only the specially marked pools in Farms are included
Points accrue only for the volume of in the LP:
○ E.g., if the LP token only has 40% of its TVL is in s-tokens, then only this 40% counts towards accrual, not the other 60%.
Accrual formula:
○ 1 point = 1$ s-token left in the pool for 1 day
Accrual frequency:
○ daily at 00:00 UTC
Each pool could have an individual multiplier that increases or decreases the total amount of accrued points.
Only cross-chain swaps receive points (as long as the route passes through the ).
Swaps below $10 do not count.
Users get 100 MetaPoints for every $10 swapped
Users can find MetaPoint accrual information on the Leaderboard in each relevant tab:
- My MetaPoints — total MetaPoints earned by the connected wallet
- In Farms — total MetaPoints earned by staking in Farms
- In Swaps — total MetaPoints earned for cross-chain swaps in Trade
- Total MetaPoints — total amount of MetaPoints earned by all the participants of the CrossCurve MetaPoints program
In the “Frams” LP staking interface, participating pools will have the icon next to them, alongside the point multiplier.
In the “Trade” interface, the expected point value of the swap will be reflected alongside points from .
1. How do I earn $S tokens Swap on CrossCurve or provide liquidity to CrossCurve pools
2. Which pools are participating in this program? Only the selected pools marked by the program’s icon in the interface
3. Does my entire staking position accrue points? No, only the part reflecting the % of in the pool
4. How is the value of the LP token determined? In USD based on the average daily value
5. How frequently do the LP points accrue? Daily
6. What can I do with MetaPoints? At the end of the , they will be converted into $S tokens
Slippage is the price change caused by external market movements and not related to the user's operation within the pool. Slippage strongly depends on the liquidity volume inside the pool. If a token pool has low liquidity, significant changes in the exchange rate within the pool require less market movement.
In the settings, you can specify slippage (by default, the parameter is set at 0.5%) Slippage is a change in price caused by external market movements and not related to the user's activity in the pool. Slippage highly depends on the liquidity volume inside the pool. If a token pool has low liquidity, significant rate changes within the pool require less market movement.
CrossCurve users can configure the maximum permissible slippage for cross-chain operation:
You can always see the exact total value in Routing details → Total slippage.
When you set a slippage tolerance in the app, this value is treated as the maximum slippage for the entire route.
● Stable pools always receive max / 10.
○ Example: if max = 1%, each first stable pool in a chain gets 0.1%.
○ Only the first stable pool in each chain applies slippage.
● Crypto pools receive the remaining slippage.
○ The remainder is evenly distributed across all chains that contain crypto pools.
○ Only the first crypto pool in each chain applies slippage.
● Other swaps in the same chain receive 0%.
● Therefore, total slippage ≤ your chosen max.
Total Slippage is the total effective slippage applied across all networks where a swap occurs during a cross-chain transaction.
It is calculated as the sum of slippage percentages for each individual network involved in the transaction.
You can find the rules for distributing slippage in the table below:
Note: Only the first pool in each chain receives slippage. Stable pools always = max/10; the rest is evenly split across crypto pools.
Change the slippage parameter only if you clearly understand why you are doing it.
If you set the value too low, you will receive a warning and your transaction may fail due to low slippage:
If you have set a value that is too high (e.g. 1%), which significantly exceeds the recommended value of 0.5%, the transaction may be executed at an unfavorable rate due to frontrun:
In Easy mode the application allows you to unbalancely add (Deposit) or withdraw (Withdraw) funds into the Curve liquidity pool with a single asset (assets that are part of the LP token or the LP tokens themselves), saving time by performing complex operations (without interacting with the Curve interface) in one click.
After selecting the necessary operation (Deposit or Withdraw) in Easy mode and clicking next (Next),
choose the network (different networks available in the CrossCurve pools, depending on the pool selected. For our example, these are: Polygon, BNB Chain, Arbitrum, Optimism, Ethereum, Base, Avalanche, and Gnosis for the xSTABLE pool.) and the token you need.
After entering the desired amount of tokens, the system will calculate the number of LP tokens received and the gas fee. By clicking Routing details, Routing will be displayed - this interface provides a convenient graphical representation of the cross-network transaction, showing all associated transitions and fees step by step.
Slippage Settings. In the settings, you can specify slippage (by default, the parameter is set at 0.5%)
The first transaction requires allowing the USD₮0 spending by clicking «Approve USD₮0» and signing the transaction in the wallet. To sign the transaction, you must hold the native token of the network in which the transaction is being made to pay for the gas.
After confirming the spending of USD₮0, a “Swap” button will appear. By pressing the "Swap" button, a request will be sent to the wallet to confirm the transaction
For convenience, a quick link to add the token to the wallet via the contract address has been added for correct balance display. By clicking on the “+”, a request will pop up to add a custom token. After signing, it will be displayed in the wallet.
There is also a method of adding liquidity to the pool – you can use multiple assets so that your operation brings the pool into a balanced state.
should be applied to avoid losses/earn profit in cases where you work with large amounts relative to the total TVL of the pool, or when the pool is close to perfect balance.
In Balanced mode the application allows adding liquidity (Deposit) in s-tokens or withdrawing (Withdraw) funds from s-tokens to the original assets of the EYWAUSDT, xCRV, xCRV2, CRV/USD, 3UNIT0, wFTMUSDC, CrossCurve frxUSD, CrossCurve frxETH, xsStable, xeWETH and xbBTC pools, CrossCurve liquidity pools with a single asset (assets that are part of the LP token or the LP tokens themselves), performing complex operations in one click.
After successfully connecting, in the Choose pool window, select the pool or asset you are interested in for working with liquidity.
Next, select the operation to deposit (Deposit) and the Balanced method of execution.
Proceeding further by pressing Next, a step-by-step mini-guide will appear:
Check the liquidity pool on Curve to find the most profitable strategy
Obtain the necessary s-tokens here on CrossCurve
Deposit liquidity in a balanced way and earn additional income on Curve
Follow the .
After successfully connecting, in the Choose pool window, select the pool or asset you are interested in for working with liquidity.
Next, choose the withdrawal (Withdraw) operation and the Balanced option.
Proceeding further by clicking Next, a step-by-step mini-guide will appear:
Check the liquidity pool on Curve to find the most profitable strategy
Withdraw liquidity in a balanced manner and earn additional income on Curve
Convert s-tokens into original assets in this window
Follow the .
To get started with the CrossCurve app. navigate to the APR calculator page in the Yield section. Click Connect wallet, select the appropriate wallet from the list, and confirm the connection, ensuring you are on the official page: https://app.crosscurve.fi/farm?&calculator=1.
After successfully connecting to the wallet, select the desired pool from the list.
The application will display information about the selected pool:
Your vAPR - total APR in the pool including the boost
Pool TVL - The total value locked in the pool
Total veEYWA - The total amount of veEYWA
To calculate the required amount of tokens for obtaining a boost, enter the desired amount of LP tokens for locking in the selected pool in the Your deposit field and adjust the slider to the desired boost level. The Your vAPR line will calculate the obtained with the selected boost.
After entering the amount of LP tokens to be locked and the desired boost, the application will calculate the required amount of tokens to achieve the boost and the desired
Your vAPR - The projected with the selected boost
You have - The balance in the connected wallet
Need for boost -The required amount of to achieve the selected boost
To obtain the necessary amount of tokens, use the by clicking Get veEYWA for BOOST.
Bridge interface description in the Aurora chain
To interact with the bridge in the CrossCurve app, go to the NFT section and select the «Gallery / Bridge» tab. Click «Connect wallet», select the right wallet from the list, and confirm the connection. Make sure that you’re on the official CrossCurve page: https://app.crosscurve.fi/nft-bridge.
After successfully connecting the wallet in the «Bridge» tab, you will see all the available NFTs in your wallet, their level of rarity, and the number of EYWA tokens within the containers.
In the top right corner, you can toggle between list and icon view options:
To migrate them to the Arbitrum chain, select up to 20 NFTs* and click «Bridge»:
* During peak hours, the Aurora network can be unstable: if you can't transfer 20 NFTs, try transferring 10 to 15 NFTs in a single transaction or try again.
In the first transaction, confirm migrating the NFTs by clicking «Approve selected NFTs»:
Then, to migrate them into Arbitrum, click «Bridge» and confirm in the wallet:
After it’s confirmed on-chain, you will receive a notification about the successful bridging of your NFTs to Arbitrum:
NOTE: After migrating your NFTs to , their copies on will be burned.
Don’t worry — all your EYWA tokens contained in those NFTs will be detached and merged if bridging multiple NFTs at once. You can always check your balance in the “.”
After the TGE, tokens will be claimable in the Claim Portal and can again be placed inside an NFT container if you so desire.

Unique NFTs from Eywa!
EYWA NFT Characters
The Eywa NFT collection includes 53 996 unique NFTs. Their number diminishes as they are merged.
The collection represents four mythical characters: Magician, Dryad, Ant, and Spider. EYWA NFTs are an example of generative art where each character features randomized attributes that grant it uniqueness.
Description of the Dashboard interface
To get started with the CrossCurve app, visit the Dashboard page. Click Connect wallet, choose your preferred wallet from the list, and confirm the connection, making sure you are on the official page:
Upon successfully connecting your wallet, the Dashboard page will display detailed information:
Example of using Easy mode for adding liquidity of the USD₮0 token into the xSTABLE LP token
To start working in the CrossCurve application, go to the section. After successfully connecting your wallet, in the Choose pool window, select the xSTABLE pool. This mode allows you to exchange a single stablecoin into the liquidity token without interacting with the liquidity pool interface on Curve.
CrossCurve is launching Sonic with an updated pool architecture built on the principle of isolated connections: each network connects to a universal asset within Sonic.
For example, the sxEthereum pool with the universal token xfrxUSD and the s-token с sUSDC_arb
This not only enhances the system's resilience but also opens direct access to all key drop programs of the Sonic ecosystem.
To begin using the CrossCurve application, go to the Early Farming Program page in the Vesting section. Click «Connect wallet», select the appropriate wallet from the list, and confirm the connection, making sure you are on the official page:
After successfully connecting your wallet, to display the rEYWA balance in your wallet, you must switch the network to Fantom by clicking Switch chain and confirming the network change in your wallet.
Once connected to the Fantom network, the application will display the rEYWA token balance in your wallet. To exchange rEYWA for the Vesting safe with EYWA, you need to move your rEYWA tokens to the Arbitrum network by clicking Bridge rEYWA to Arbitrum and singing the transaction in your wallet.
CrossCurve SuperDVN is a verification module (DVN, Decentralized Verification Network) compatible with the LayerZero . It leverages the CrossCurve Consensus Bridge as its internal mechanism for cross-chain message verification and transmission.
SuperDVN serves as a sovereign data verification layer for cross-chain applications, providing a decentralized, secure, and resilient environment for communication between blockchains.
Example of using Easy mode for withdrawing liquidity of the EUSD LP token into the USDT stablecoin
To start working in the CrossCurve application, go to the section. After successfully connecting your wallet, in the Choose pool window, select the EUSD pool. This mode allows you to exchange the liquidity token into a single stablecoin without interacting with the liquidity pool interface on Curve.
Step 1. Go to on Curve and analyze the optimal way to withdraw funds from the pool:
A balanced method of withdrawing liquidity from the pool is recommended – you will receive s-tokens in proportion from several assets so that your operation brings the pool into a balanced state.
Step 2. After connecting the wallet, go to the Withdraw/Claim tab and use the Balanced mode. After entering the amount to be withdrawn, the AMM will distribute the s-tokens in proportion to the pool's balance from the total TVL.
DelegationConditionValidatorV1 This is an upgradeable contract that allows you to set additional conditions for delegating locks. It is integrated with EscrowManager, which allows you to know the current status of the lock when delegating it.
Key Roles and Features:
Access Control: Restricts setAssuranceLockParameters
Now, every CrossCurve user can earn three types of rewards just by interacting with the app.
Currently, Sonic incentives are provided for all paired pools on Sonic and for the 3UNIT0 pool.
This is the core drop mechanism from Sonic, focused on end users. Points are awarded for holding whitelisted assets and come in two types: passive (for storing assets in a wallet) and active (for using assets in third-party apps, such as CrossCurve), which earn double the passive rate.
Thus, farming Sonic Points through CrossCurve is twice as profitable!
The following assets offer different boosts:
scUSD — 6x
scETH, scBTC — 4x
At the end of the drop, Sonic Points will be converted into NFT-safes, from which $S tokens will gradually unlock. All information is displayed in the dashboard: my.soniclabs.com/points
This is a separate program for protocols and the second part of the Sonic drop. During the first season, 1 680 000 Gems will be distributed. 262 500 have already been pre-allocated to the winners of Sonic Boom. CrossCurve, as one of the winners in the Sapphire tier, has already received 8750 Gems. The remaining 1 417 500 Gems will be distributed based on user activity and multipliers. For CrossCurve as a bridge, a 5x multiplier applies.
We’ve decided to tokenize these as cmGEMS1 and allocate 100% of these tokens as rewards to liquidity providers in the project’s pools.
But perhaps the main advantage of cmGEMS1, unlike Points, is that they can be directly exchanged for $S.
Rings Protocol is the issuer of the stablecoins scUSD, scETH and scBTC, which are present in the Sonic pools on CrossCurve. The protocol has its own drop program — Rings Points, which are awarded automatically, similar to Sonic’s own.
Like Gems, Rings Points can be directly exchanged for $S at the end of the season.
This is the core drop mechanism from Sonic, focused on end users. Points are awarded for locking whitelisted assets in CrossCurve pools.
The following assets offer different boosts:
scUSD — 6x
scETH, scBTC — 4x
All information is displayed in the dashboard: my.soniclabs.com/points
CrossCurve’s transition to Sonic is not just an upgrade, but a real expansion of economic opportunities for our liquidity providers. With the new pool architecture, almost every provider can receive triple incentive accrual - not counting CrossCurve’s own rewards.
Sonic incentives apply to all paired pools in the Sonic network, as well as the UNIT0 pool.






































Stable → Crypto
0.1% → 0.9%
1%
Stable → Stable → Crypto (3 chains)
0.1% → 0.1% → 0.8%
1%
Crypto → Crypto → Crypto (3 chains)
0.33% → 0.33% → 0.33%
1%
Crypto → Crypto → Stable (3 chains)
0.45% → 0.45% → 0.1%
1%
Stable → Crypto (2nd chain)
0.1% → 0.9%
1%
Stable → Crypto → Stable (3 chains)
0.1% → 0.8% → 0.1%
1%
Stable
0.1%
0.1%
Crypto
1%
1%
Stable, Stable (same chain)
0.1% → 0%
0.1%
Stable → Stable (2 chains)
0.1% → 0.1%





0.2%
250 000
infinity
3
1 500 000
















owner()Upgradeable via UUPS: Uses UUPSUpgradeable and OwnableUpgradeable patterns, restricting contract upgrades to the owner.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality under the UUPS proxy pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Manages ownership, allowing only the owner to modify critical parameters and authorize upgrades.
ILockHolderFactoryV1:
Defines core methods (e.g., createLockHolder) and events for this contract.
Additional External References:
ERC1967Proxy (OpenZeppelin): A proxy implementation that stores the logic contract address in storage per EIP-1967.
LockHolderV1: LockHolder contract.
s_escrowManager (address)
Address of the EscrowManager contract.
s_escrowVoteManager (address)
Address of the EscrowVoteManager contract.
s_delegationManager (address)
Address of the DelegationManager contract.
s_incentiveRewardsAggregator (address)
Address of the IncentiveRewardsAggregator contract.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
Description: Configures ownership, references, and initial state:
References the EYWA NFT, escrow manager, escrow vote manager and delegation manager.
Parameters:
owner_: The address of the contract owner.
escrowManager_: The address of the escrow manager contract.
escrowVoteManager_: The address of the escrow vote manager contract.
delegationManager_: The address of the delegation manager contract.
incentiveRewardsAggregator_: The address of the incentive rewards aggregator contract.
Description: The function deploys and initializes an upgradable LockHolder contract. Returns the address of the LockHolder contract.
Checks:
sender must be a DelegationManager contract. Otherwise, UnauthorizedCaller() is thrown.
Events:
Emits LockHolderCreated(m_lockHolder, m_implementation).
LockHolderCreated(address indexed lockHolder, address indexed implementation))
Emitted when a new LockHolder is created.
UnauthorizedCaller()
Thrown when the caller is not the delegation manager.
LockHolderFactoryV1 contract is an important part of the lock delegation architecture. It deploys a new LockHolder contract for each delegator-delegate pair, which provides the ability to reliably track the movement of delegated locks, manage them, and receive and distribute rewards.
owner()Upgradeable via UUPS: Uses UUPSUpgradeable and OwnableUpgradeable patterns, restricting contract upgrades to the owner.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality under the UUPS proxy pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Manages ownership, allowing only the owner to modify critical parameters and authorize upgrades.
IDelegationConditionValidatorV1:
Defines core methods (e.g., validateDelegations) and events for this contract.
Additional External References:
IDelegationManagerV1: Management of delegated locks
IEscrowManagerExtended: Holds locked token data and checks voting power and freeze logic.
s_escrowManager (IEscrowManagerExtended)
IEscrowManager interface for the EscrowManager contract.
s_delegationManager (IDelegationManagerV1)
IDelegationManagerV1 for the DelegationManager contract.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
Description: Configures ownership, references, and initial state:
References the escrow manager and delegation manager.
Parameters:
owner_: The address of the contract owner.
escrowManager_: The IEscrowManager interface for the EscrowManager contract.
delegationManager_: The IDelegationManagerV1 for the DelegationManager contract.
Description:
The function performs checks and determines whether delegation of tokenIds_ from delegator_ to delegatee_ is possible.
Parameters:
delegator_: The address of the contract owner.
delegatee_: The IEscrowManager interface for the EscrowManager contract.
tokenIds_: The IDelegationManagerV1 for the DelegationManager contract.
Checks:
sender must be a DelegationManager contract. Otherwise, UnauthorizedCaller() is thrown
UnauthorizedCaller()
Thrown when the caller is not authorized to perform the action.
DelegationConditionValidatorV1 Being updatable in the long run can provide the opportunity for varied and flexible customization for delegated locks.
constructor() {
_disableInitializers();
}function initialize(
address owner_,
address escrowManager_,
address escrowVoteManager_,
address delegationManager_,
address incentiveRewardsAggregator_
) external initializer;function createLockHolder() external returns (address);constructor() {
_disableInitializers();
}function initialize(
address owner_,
IEscrowManagerExtended escrowManager_,
IDelegationManagerV1 delegationManager_
) external initializer;function validateDelegations(
address delegator_,
address delegatee_,
uint256[] calldata tokenIds_
) external view returns(bool);0% — Grant incentives.
37% — Bribe incentives.
The characters in the collection are unique creations, drawing inspiration from beloved science fiction universes.
The Magician Crafted from leaves and various flora types, the magician is inspired by the Star Wars universe and Elemental creatures, as well as ancient Roman and Greek mythology.
The Dryad This character is inspired by ancient Greek myths, aliens, and the golden era of science fiction, presenting a stunning fusion of a wood nymph with a World of Warcraft (WoW) hero.
The Ent Assembled from tree bark and roots, the Ent is inspired by the Ents from the Lord of the Rings (LOTR) universe, Swamp Thing from DC Comics, and Groot from Marvel.
The Spider The spider character embodies an aggressive, dynamic figure, combining an arachnid with a trickster — a mix of Baal from Diablo II, Monsters, Inc., and other characters, infused with elements of insects and alien life forms.
We have deliberately directed our design team to embrace a “fairytale” aesthetic in the creation of our characters' likenesses. Regardless of age, we all cherish a touch of magic in our lives.
Echoing the words of Steve Jobs: “Follow your heart, stay hungry, stay foolish!” we are committed to developing the finest cross-chain product on the market. Thank you for your support!
The collection is broken down into five levels of rarity: Common, Uncommon, Rare, Legendary, and Infinity. The rarest of all are the Magician Infinity NFTs, of which there are only 193 in the entire EYWA NFT collection.
Currently, the collection is available on the Aurora and Arbitrum networks:
On the Aurora network, the collection is available for trading within our Telegram communities (Links to Telegram chats for trading Eywa NFTs: English speaking region CIS region).
On the Arbitrum network, the collection is available for trading on OpenSea.
The EYWA NFT collection is composed of ERC-721 tokens with the following unique functions:
• Container function for storing up to 1 500 000 EYWA tokens
• Merge function that allows you to increase the size of the container and the rarity of the NFT by combining multiple NFTs of one level into one rarer NFT
• CrossCurve DAO vote multiplier function via veEYWA
Each NFT in the collection functions as a container for EYWA tokens. You can attach both unlocked and locked in vesting safes* tokens to the NFT. This allows the user to sell blocked EYWA tokens at any time.
The capacity of each NFT is the maximum number of EYWA tokens it can contain and depends on the rarity of the NFT. The highest capacity — 1 500 000 EYWA — is reserved for the Infinity rarity level NFTs. In the Aurora chain, you can see your current balance of token in the container. Once migrated to the Arbitrum chain, the tokens will be separated from the NFT and can be received as vesting safes via the Claim portal after the TGE.
For details, see the table below:
common
500
uncommon
3 000
rare
25 000
legendary
250 000
infinity
1 500 000
Several NFTs of the same type can be merged to create a single NFT with a higher rarity level. This will also merge all of the tokens contained in the source NFTs.
Multiplier table for NFT merging:
common
5
1 uncommon
uncommon
7
1 rare
rare
9
1 legendary
legendary
n/a
n/a
To vote in the CrossCurve DAO, users must lock EYWA tokens — the longer the lock period, the more voting power the user gets. Using EYWA NFTs can also increase voting power. Each NFT can increase the number of available votes by the maximum number of tokens it can contain.
For details, see the table below:
common
500
1.006
uncommon
3 000
1.036
rare
25 000
1.3
legendary
250 000
After the NFT collection is migrated to the Arbitrum chain, all of the above functions will become available. Before the TGE, we will open up a bridge to move the NFTs from Aurora to Arbitrum, as well as the NFT Manager to fully engage with all of the functions of the NFTs.
The NFT Manager will ensure access to tokens contained in the NFTs, which will be separated from their containers after the migration to Arbitrum and be put together in each user’s wallet. Users will be able to put tokens into vesting safes and keep rEYWA in the NFTs.
Farms - shows your liquidity provided in CrossCurve pools and farming rewards earned.
It also presents statistics for pools you've joined:
Pool - pool name
Staked - quantity of LP tokens you've staked
APR - current pool yield
Earn - farming rewards earned
To collect your rewards, click Claim and sign the transaction in your wallet, or navigate to the Farms page via the Go to Farms link to manage liquidity and earn rewards on Angle Merkl
Vested - displays EYWA tokens in vesting safes, locked in DAO, and tokens available for claiming upon vesting completion.
Claimable safes section shows the number of safes ready to be claimed and total token amount inside. To claim these vesting safes, click Get your safes and confirm the transaction in your wallet.
Vested safes section shows the total number of vesting safes and the token amount contained. Ready to claim displays EYWA tokens with completed vesting periods, available for claiming. To receive these tokens, visit the Claim Portal.
Early Farming Program section shows the amount of rEYWA tokens earned from early liquidity provision in CrossCurve pools (more details here). To exchange rEYWA tokens for EYWA, follow the Go to rEYWA link in the Early Farming Program section.
Locked in DAO displays your DAO locks, total tokens locked, and the nearest lock expiration date. For a full list of locks in the Locker, click View.
DAO Rewards - shows rewards earned from DAO participation.
The Incentives section shows rewards received for your votes on CrossCurve pools. To claim these rewards, click Claim and sign the transaction in your wallet.
NFT - displays EYWA tokens contained within EYWA NFT containers pending vesting, and the number of EYWA NFTs in the connected wallet.
Aurora-NFT-detached EYWA tokens, post-bridging to Arbitrum - displays EYWA tokens detached from EYWA NFTs after bridging from Aurora to Arbitrum (more details here). These EYWA tokens can be claimed as vesting safes by clicking Claim and signing the transaction in your wallet.
In wallet - shows the number of EYWA NFTs and the EYWA token amount within NFT containers. Click View to see detailed information.
In lock - indicates the number of NFTs in locks. Click View to go to NFT Manager for detailed information.
Having selected the Deposit operation and Easy mode, proceed to the exchange modal window by pressing Next.
Next, select the USD₮0 token (or any other available asset participating in the xSTABLE pool) to add the liquidity and choose the preferred network of the received original asset.
After entering the desired amount of tokens, the system will calculate the number of LP tokens received and the gas fee. By clicking Routing details, Routing will be displayed - this interface provides a convenient graphical representation of the cross-network transaction, showing all associated transitions and fees step by step:
The first transaction requires allowing the USD₮0 spending by clicking «Approve USD₮0» and signing the transaction in the wallet. To sign the transaction, you must hold the native token of the network in which the transaction is being made to pay for the gas.
After confirming the spending of USD₮0, a “Swap” button will appear.
By pressing the "Swap" button, a request will be sent to the wallet to confirm the transaction of depositing the USD₮0 token into the xSTABLE pool on Curve.
After signing the transaction, a notification about the sending, the ongoing exchange, and the estimated waiting time will be received. The status and progress will be displayed in the top right corner.

To use the bridge and transfer your rEYWA from the Fantom network to Arbitrum, you must have FTM in your Fantom wallet to sign the transaction and pay the gwei in the Fantom network.
After successfully transferring rEYWA from Fantom to Arbitrum, the application will display the balance of the transferred tokens. To start the 90-day vesting period and receive EYWA tokens in exchange for rEYWA, click Start vesting, specify the amount of rEYWA you want to vest, and confirm the transaction in your wallet.
After placing rEYWA into vesting, the application will display detailed information:
Vested - amount of rEYWA tokens that have completed vesting
Current vesting - the total amount of rEYWA currently in vesting
In the table, you will see detailed information about ongoing vesting periods:
Amount - the amount of rEYWA tokens for each vesting period
Date - the vesting end date and the number of remaining days. Complete means completed vesting periods.
Penalty - the amount of penalty* in rEYWA tokens for early termination of vesting
* You can find detailed information by following the link or by clicking
To receive rEYWA tokens after the vesting period ends, select the vesting safe and click Withdraw, then confirm the transaction in your wallet.
To end the vesting period early and receive rEYWA tokens minus the penalty*, click Exit and confirm the transaction in your wallet.
Where:
V early - number of rEYWA tokens received on the day T
T - number of vested days passed since the rEYWA claim
V all - total number of rEYWA tokens available on the 91st day, after the vesting period is completed
* You can find detailed information by following the link or by clicking
LayerZero uses DVNs to achieve decentralized verification of cross-chain message transfers. However, ensuring robust security requires two or more independent DVNs.
For developers, SuperDVN appears as a single DVN, but internally it contains a consensus layer composed of multiple messaging protocols, combining their verification capabilities for enhanced reliability and trustlessness.
The OApp application sends a message on the source network to the LayerZero Endpoint contract.
The LayerZero protocol processes the message in its standard way and forwards it for verification to the CrossCurve DVN contract.
The CrossCurve DVN prepares and sends the verification data to the CrossCurve Gatekeeper.
The Gatekeeper dispatches this data through multiple messaging protocols.
Each protocol, following its standard cross-chain messaging procedure, independently delivers the data to the CrossCurve Receiver contract.
The Receiver collects the incoming message instances and emits events upon receipt.
The external service CrossCurve Pusher monitors these events. Once the original message and a sufficient number of verification confirmations are detected, it submits an execution transaction to the CrossCurve Receiver contract.
Upon receiving the transaction from CrossCurve Pusher, the Receiver checks that the original message and all required protocol confirmations are present.
If verification succeeds, the data is passed back to the CrossCurve DVN, which forwards the verification data to the ReceiveLib contract to complete the verification process and allow LayerZero to proceed with message delivery.
SuperDVN is fully compliant with the LayerZero DVN Standard, which provides:
Ability to connect as a primary DVN for cross-chain messaging between networks using LayerZero.
Support for custom DVN, allowing SuperDVN to be used for specific applications.
Compatibility with the LayerZero ecosystem without the need to modify smart contracts.
SuperDVN leverages CrossCurve Consensus Bridge to enhance verification security.
Currently, the Consensus Bridge supports the following messaging protocols:
CrossCurve Oracle Network
To integrate SuperDVN into an OApp, you need to configure the ULN as specified in the LayerZero documentation.
Here is an example configuration for using a single SuperDVN:
SuperDVN.address — the address of the SuperDVN contract on the OApp network that sends the message.
To configure the OApp, use the following contract addresses:
Ethereum Sepolia Testnet
Arbitrum Sepolia Testnet
Having selected the Withdraw operation and Easy mode, proceed to the exchange modal window by pressing Next.
Next, select the USDT stablecoin (or any other available asset participating in the EUSD pool) to withdraw liquidity and choose the preferred network of the received original asset.
After entering the amount of tokens to be withdrawn, the system will calculate the number of LP tokens received and the gas fee. By pressing Routing details, the Routing will be displayed.
The first transaction requires allowing the spending of EUSD by pressing “Approve EUSD” and signing the transaction in the wallet. For signing the transaction, you must hold the native token of the network in which the transaction is being conducted to pay for the gas.
After confirming the spending of EUSD, a “Swap” button will appear.
By pressing the "Swap" button, a request will be sent to the wallet to confirm the transaction of exchanging the EUSD LP token from the EUSD pool to the USDT stablecoin on the Arbitrum network.
6. After signing the transaction, a notification about the transaction sending, the ongoing exchange, and the estimated waiting time will be received. The status and progress will be displayed in the top right corner.
This method should be applied to avoid penalties and earn additional profit on Curve in cases when you are working with large sums relative to the total TVL of the pool, or when the pool is close to perfect balance. After pressing Withdraw, confirm the operation in the wallet. After completing the operation, the system will issue a Withdraw Complete message.
Step 3. Convert the required s-tokens in the CrossCurve interface.
In the Input window, select the s-token for conversion and specify the amount of s-tokens to be converted.
2. In the Output window, select the token for conversion, approve the spending of the s-token by clicking Approve scrvUSDC_o, and confirm the transaction in the wallet.
After approving the spending of scrvUSDC_o, a Swap button will appear.
4. By pressing the "Swap" button, a request will be sent to the wallet to confirm the transaction of exchanging the scrvUSDC_o s-token for the selected crvUSDC LP.
5. After signing the transaction, a notification about the transaction sending, the ongoing exchange, and the estimated waiting time will be received. The status and progress will be displayed in the top right corner.
CrossCurve provides a user-friendly experience for conducting operations between different blockchains. All cross-chain transactions, such as token transfers, cross-chain stablecoin exchanges, and cross-chain buying and selling of assets, can be performed from a single interface.
Step 1. To access CrossCurve DEX, go to https://app.crosscurve.fi/.
Step 2. Go to the Trade section.
Step 3. Connect your wallet by clicking the Connect wallet button in the top right corner.
Step 4. In the FROM field, specify the token and the network from which you are sending. This can be done in a special modal window that appears when you click on the network or token icon.
Step 5. In the TO field, specify the token and the receiving network.
Step 6. In the FROM field, enter the amount of tokens you are sending. The amount of tokens you will receive in the TO field will be calculated automatically.
Step 7. Review the details of the cross-chain operation. In the dropdown menu, you can review the key details of the cross-chain operation:
Routing details - full information about all cross-chain swaps for the selected transaction (details here)
Expected amount - approximate amount you will receive after taking out the fee
Total slippage - total effective slippage applied across all networks where a swap occurs during a cross-chain transaction, calculated as the sum of slippage percentages for each individual network involved in the transaction
Gas cost reflects the gas fee in Gwei (details ). Expected transfer time indicates the time the transaction is expected to take. The “You’ll get” line shows the amount of points you will receive in the loyalty programs of Airdrop Season 2 and MetaPoints (details and ).
Step 8. Give the CrossCurve application Approve or Permit permission for the CrossCurve smart contracts to interact with the assets you are sending, as specified in the FROM field.
Step 9. Click the Swap button to execute the cross-chain operation.
If the transaction has a high price impact, an additional window will appear before signing the transaction, where you will need to confirm the operation. This is to prevent accidental loss of user funds.
Step 10. Sign the transaction in the wallet connected to the app.crosscurve.fi application.
After submitting a cross-chain transaction, you can track the progress of the cross-chain operation in the Transaction history:
Each cross-chain operation consists of multiple stages. In the Transaction history section, users can track the status of its execution and review its component transactions.
If a cross-chain operation was interrupted for any reason, you will see an appropriate notification in the Transaction history. The interface will provide options for further actions. For more detailed information, you can refer to the Error in Cross-Chain Operation section.
A modal window is used for selecting networks and tokens:
On the left side, click on the desired network. The right side will display all available tokens for sending/receiving in that network. You can use the search function to find a specific token by its name or smart-contract address.
For your convenience, you can Search by name of the token’s ticker or by its smart-contract address.
Hovering over any token will show a quick link for adding that token to your wallet and a link to that token’s smart-contract address on the scanner.
When entering Advanced mode, you’ll see a filter for sorting tokens as: All, USD, ETH, BTC, Other
Open the Curve DAO Token (CRV) contract in FTMScan:
Go to the Contract tab, choose Write Contract, and connect your wallet by clicking Connect to Web3.
Expand the approve submenu for the Curve DAO Token (CRV) contract and make sure the _spender address is the following bridge contract:
Enter the number of tokens to approve for moving (in Wei format, meaning that you need to add 18 zeroes to the end of the amount or click and choose the right format).
Here is an example for approving 10,000 CRV tokens:
Click and sign the Token Approval transaction in your wallet.
After a successful Token Approval transaction, find the Layer Zero Bridge contract for Curve DAO Token (CRV) in FTMScan:
Go to the Contract tab, then Read Contract.
Click on the 1. quote tab, after which you will see the current Wei cost of the transfer. Click on that to open the converter. Copy the FTM (1) value.
Go to the Write Contract tab and connect your wallet by clicking Connect to Web3.
Click on the 1. bridge (0xc3de453d) tab, after which you’ll see a form with 3 fields to be filled out as follows:
In the bridge field, enter the value you copied from 1. quote.
In the _receiver (address), enter the receiving Ethereum address (your own, if sending to yourself).
In the _amount (uint256) field, enter the number of tokens (in Wei format: add 18 zeroes to the end of the amount or click and choose the right format).
Example of filling out the fields for transferring 10,000 CRV tokens:
Click and sign the Bridge transaction in your wallet. Your transfer has now been sent. You can find the status and other details of the transfer here:
EYWA NFT Manager interface description
In the EYWA NFT Manager, users can see information about the number of EYWA tokens in each NFT container and vesting periods simply by entering the ID of any NFT in the collection. After connecting their wallet, users can also manage their vesting safes* and add EYWA tokens to NFT containers**.
To find an NFT’s container and vesting information using its ID, one should go into the «» section, connect his wallet, and enter the number into the «NFT ID» field:
To find the NFT ID, go to the collection page for EYWA NFTs, making sure that the address matches the original address of the collection:
Choose an NFT of interest and go to its page.
You will see the NFT ID in the name of the selected NFT.
To quickly get into the app, use the View website link in the More menu.
After entering the NFT ID into the search bar, the EYWA NFT Manager will show you information about the found NFT:
On the EYWA NFT Manager page, you can use the “search via NFT ID” function or choose one of your NFTs from the My NFTs gallery.
After selecting the NFT, the search window will show detailed information:
• NFT rarity and remaining space in the container
• Total number of tokens in the safe
• Rounds in which the EYWA tokens were received and their vesting period: total number of received tokens in each round, number of unlocked tokens, and when the vesting of the locked tokens ends
Detailed information about rounds and visiting periods can be found.
Attention! If you buy NFT with EYWA tokens in a container, we recommend using the Buy now function to avoid detaching EYWA tokens before confirming the purchase. If you are buying on an Auction by sending your Offer or on an OTC marketplace - there is a possibility of falling for an unscrupulous seller who may detach the tokens from the container before sending the NFT to the buyer. The Buy now instant purchase feature on significantly reduces this risk.
To manage your NFTs in the CrossCurve app, you need to go to the Manager page in the NFT section. In the top right corner, click on «Connect wallet», select the right wallet from the list, and confirm the connection, making sure that you are on the official page:
After successfully connecting the wallet, in the «Total in wallet» tab you will see your total EYWA token balance (wallet Balance plus vesting safes) as well as information about rounds where these tokens were received and their vesting period:
• Total number of tokens received in the round
• Number of unlocked tokens
• End of vesting period for locked tokens
In the My NFTs section, you’ll see all the EYWA NFTs from the connected wallet with detailed information about each one:
ID
Rarity
Number of EYWA tokens in the NFT container
To remove tokens from the NFT container, enter the number of tokens and click «Detach from NFT». Then confirm in your wallet:
After the on-chain confirmation of the transaction, you will receive a notification that the NFT safe was successfully updated:
To attach tokens to an NFT safe, enter the number of EYWA tokens, select the vesting safes that contain those tokens, and click «Attach to NFT». Then confirm in your wallet:
When adding tokens to NFTs, safes of the same type and vesting period are merged.
After the on-chain confirmation of the transaction, you will receive a notification that the NFT safe was successfully updated:
Incentives Interface Description
Incentives interface provides access to the ve(3,3) mechanism in the CrossCurve DAO for external projects and protocols, as well as for veEYWA holders.
Now, owners of locked EYWA tokens (veEYWA) can receive additional rewards for participating in votes for specific liquidity pools, significantly expanding the earning opportunities within the ecosystem. Meanwhile, external projects can acquire liquidity, gain visibility, and secure their status in the cross-chain space.
To get started in the CrossCurve application, go to the Incentives page in the DAO section. Click “Connect wallet”, select a suitable wallet from the list, and confirm the connection, making sure you are on the official page:
On the Incentives page, detailed information will be displayed:
Current voting round ends in - remaining time until the voting period ends in this epoch
Farm pools - pool name and its statistics:
Basic Volatile - pool type*
* CrossCurve offers two distinct liquidity pools to users: the Stable Pool and the Volatility Pool.
Volatility Pools consist of liquidity (Curve pools) for asset pairs with volatile prices, typically experiencing divergence. For example, USDT vs. EYWA or ETH vs. BTC.
Volatile pairs are formed by combining uncorrelated assets and utilize Curve's unique impermanent loss compensation mechanism for pools containing volatile assets.
Stable Pools are pools of stable liquidity (Curve pools) between assets whose prices are pegged to each other. For example, USDT vs. USDC.
Another case involves derivative assets, such as wstETH and rETH. Although rETH is considered a volatile asset, the trading pair between wstETH and rETH is classified as a stable pool because the price of wstETH does not significantly fluctuate relative to rETH.
Votes - number of veEYWA votes cast and the percentage of total votes received by this pool among all pools participating in the vote
Chain - the network in which the pool operates
TVL - total value locked in the pool
Volume (24h) - trading volume in the pool over 24 hours
Attention: The Incentives function is mainly used by protocols. Please ensure that you understand how it works before using it, as any transaction is final and cannot be reversed. For more detailed information, follow the Read docs link.
For easier navigation, use the filter icon to search for a specific network or token within a pool.
To propose a reward for all CrossCurve DAO participants in exchange for their votes in the next epoch, select the pool to which you want to allocate rewards. At the beginning of the next epoch, these rewards will be evenly distributed among all those who voted for that pool.
In the modal window that appears, select the token in which you want to add rewards and enter the amount to be allocated.
To proceed with adding the selected rewards to the pool, you must give consent by checking the box, as any transaction is final and cannot be reversed, meaning the allocated tokens cannot be refunded.
After confirming your agreement with the reward allocation terms, click Add Incentive and sign the transactions to approve spending (Approve) and add the rewards (Add Incentive)
By navigating to the page in the DAO section, you can view the amount of allocated rewards for DAO participants in the current and upcoming epochs:
Estimated EYWA emission in the next epoch - average amount of rewards allocated for the next epoch in EYWA tokens
Estimated CRV emission in the next epoch - average amount of rewards allocated for the next epoch in CRV tokens
Estimated incentives available in the current epoch - average amount of rewards allocated for the current epoch in USD equivalent
The reward amounts allocated to voters for each pool are displayed in the Incentives column.
On the page in your personal statistics, rewards are calculated in the Incentives section. At the end off the epoch, rewards become available for claiming. To claim your rewards, click Claim and sign the transaction(s) in your wallet.
To start using the CrossCurve app, navigate to the Claim portal page in the Vesting section. Click «Connect wallet», select the appropriate wallet from the list, and confirm the connection, ensuring that you are on the official page: https://app.crosscurve.fi/vesting
After successfully connecting your wallet, the app will verify your wallet address against the criteria for eligible EYWA tokens to claim. Please wait for the request to be processed.
If, after the wallet verification request, you see a message stating that the wallet address was not found on the token claim list, please verify the accuracy of the connected wallet address. If you believe an error has occurred, contact support to repeat the verification process:
for private round participants, e-mail;
for public round participants, .
After successful verification, you will see all vesting safes available for your wallet address, containing EYWA tokens received in each distribution round. To manage vesting safes, click Get your vesting safes and confirm the transaction in your wallet.
Read more about rounds .
After successfully confirming the transaction, all vesting safes available for the connected wallet will be displayed.
In each type of vesting safe, the following information is displayed:
All vested tokens - the number of tokens in the safe that are in vesting
Amount to claim - the available amount of tokens to claim
Already claimed - the number of tokens already claimed from the vesting safe
Time remaining until next claim - the remaining vesting time before tokens can be claimed from the safe
If you have multiple vesting safes for a single round, their number will be displayed in the upper right corner of the safe.
To view detailed information about grouped safes received in one round, hover your cursor over that safe.
Attention! If you see the Claim button inactive - don't worry, it will become active immediately after the listing of EYWA token on CEX. The vesting timer will also start counting from the listing date.
To claim available tokens, select the safe and click Claim, then confirm the transaction in your wallet.
To claim available tokens from grouped safes, click Open to claim.
Choose the safe to claim tokens from, click Claim and confirm the transaction in your wallet.
Introducing «Early Farming» — a farming program for early liquidity providers!
For providing liquidity in CrossCurve pools, the participants will receive rewards in rEYWA tokens. rEYWA — a non-transferable reward token (reward EYWA) that after the listing can be traded for the EYWA token on a 1:1 basis. Participants receive the rewards based on the rules of the Early Farming program, based on the volume of liquidity provided and the pool selected:
These pools allow the participants to receive earnings (Net APY) that combines the base rEYWA earnings per the above table + vAPY in .
*The rEYWA APR is calculated at the EYWA price of $0.14. You can use this calculator to simulate your earnings with different EYWA prices:
rEYWA tokens have a 90-day vesting period starting from the claim, which can be done at any time. Once the vesting period is over, rEYWA can be converted to regular EYWA tokens 1:1. Exchanging rEYWA to EYWA is possible only after the listing.
If a participant wishes to do this exchange prior to the completion of the vesting period, he will be able to convert only those rEYWA that have vested based on the vesting schedule. The rest of his rEYWA will be returned to the CrossCurve DAO’s treasury.
The formula for exchanging rEYWA for EYWA before the 90-day vesting period ends is as follows:
Where:
V early - number of rEYWA tokens received on the day T
T - number of vested days passed since the rEYWA claim
V all - total number of rEYWA tokens available on the 91st day, after the vesting period is completed
Participants can choose to wait until the vesting period is over or take part of their tokens earlier based on their needs and strategy.
Where:
T = 21 (vesting days since the claim),
V all = 10,000 rEYWA (total number of rEYWA tokens that could be claimed on day 91).
Therefore, on day 21, the participant would only receive 500 rEYWA out of 10,000. These are the tokens he would be able to exchange for EYWA after the listing. The remaining 9,500 tokens would be returned to the DAO's treasury.
To start working in the CrossCurve app, go to the Farms page in the Yield section. There, click “Connect wallet” in the top right corner, choose a suitable wallet from the list, and confirm the connection, making sure you are on the original page https://app.crosscurve.fi/farms.
After successfully connecting, you will see all available pools for staking LP tokens in the selected network to earn EYWA or/and CRV.
Farm Pool - Pool name
Chain - Network where the pool is located
TVL - Total volume of funds in the pool
Volume - Trading volume in the pool for the past 24 hours
By clicking on the APR Calculator icon, you will see a modal window to calculate your actual vAPR and boost for your deposit based on veEYWA ownership and the resulting EYWA NFT boost. More details you can find here.
By clicking on the vAPR icon you will see detailed information about the rewards in the selected pool.
Current vAPR - Current “Variable Annual Percentage Rate”: it is the interest you'd earn on your deposits for a whole year, and it's variable because it depends on today's trading activity in this pool, the price of the assets you deposit, the price of the assets you're rewarded with, and the current rewards rates.
Base pool vAPR - “Base pool vAPR” accrues within the CrossCurve pool: this yield does not require claiming; it is automatically accumulated within your LP token.
CRV cAPR - “CRV vAPR” is distributed separately and can be claimed on the “Farms” page in the “Farming rewards” section. The amount of this yield depends on your veCRV boost.
By expanding the details window of the selected pool, you can find a link to obtain the LP token via CrossCurve, or through Curve pools and Pool Contract (leads to the pool's LP token contract). You can also find a direct link to rewards dashboard.
In the Farming rewards window, accrued earnings from farming are displayed.
Staked shows the balance of LP tokens locked for earning EYWA and CRV.
By clicking ‘Stake LP and get rewards’ we will see a modal window of steaking to get EYWA and CRV.
In the field for entering the amount of LP tokens to be deposited, enter the desired amount. By clicking the Get LP link, you can obtain additional tokens on CrossCurve.
The top menu allows sorting the display of pools:
By relevance
By type (Stablecoin, crypto or any pools)
By Popularity, APR, TVL, Liquidity Utilisation and Volume

By visiting the main page at , you enter the CrossCurve Application Interface, where you can see three main sections: the Interface for executing token exchange transactions between different networks ( tab), the user interface for interacting with the , , and ( tab), the statistics page along with referral count ( tab), the Interfaces for working with liquidity and yield strategies on CrossCurve ( menu), and the menu for interacting with Vesting Safes and rEYWA ( menu). There is also a quick link to the where yields are reflected ( tab) and a menu for quick purchasing of $EYWA
Proposals provides the CrossCurve DAO community with tools to manage and guide the protocol's development:
- A platform for managing and voting on proposals impacting the CrossCurve protocol
- Decentralized decision-making by token holders
DAO members actively participate in shaping the CrossCurve protocol by:
Creating proposals: members can introduce initiatives such as protocol parameter adjustments or fund allocation.
To provide liquidity to Sonic pools:
Select the pool where you want to transfer liquidity, e.g., xsArbitrum.
Determine the required token amounts.
CalldataHelperV1 is an upgradeable contract that assists with decoding and slicing transaction calldata. It extracts critical parameters such as method-specific calldata, a target address, and a chain identifier from a given input. This functionality is useful in scenarios where cross-chain calls or proxy calls need to parse custom-encoded calldata.
By implementing ICalldataHelperV1, the CalldataHelperV1 contract ensures a standardized interface for:
LockHolderV1 is an upgradeable contract integrated with DelegationManager, EscrowManager, EscrowVoteManager, IncentiveRewardsAggregatorV1. For each delegator-delegate pair, a different LockHolder contract is deployed, with delegated locks in the balance. Through the LockHolder contract the proxied call of functions of EscrowManager, EscrowVoteManager counters, as well as collection and distribution of incentive rewards takes place.
Key Roles and Features:
Vote Interface Description
tokens provides unique opportunities to earn additional income by receiving on specific . holders use their votes to direct across CrossCurve pools. Projects seeking liquidity offer incentives (various tokens) to holders in exchange for their votes.
tokens transforms voting rights into income streams: veEYWA holders select the most beneficial proposals and receive rewards in tokens, cryptocurrencies, or other forms of income from participating projects. The higher your veEYWA balance, the greater your potential rewards.
RewardsDistributorFactoryV1 is an upgradeable contract (using UUPS) that deploys new instances of IncentiveRewardsDistributor. It restricts calls to createRewardsDistributor such that only the escrow vote manager can request a new distributor, thus ensuring controlled creation of additional reward distribution contracts.
Key Roles and Features:
Treasury is a minimal yet crucial smart contract that securely stores and allows controlled withdrawals of both native ETH and ERC20 tokens. Owned by a single address, it enforces strict access control on asset movements via onlyOwner and mitigates re-entrant calls through nonReentrant. This design ensures that only the contract owner can authorize withdrawals and that no re-entrancy exploits can siphon funds.
Key Attributes:
const ulnConfig = {
confirmations: 1,
requiredDVNCount: 1,
optionalDVNCount: 0,
optionalDVNThreshold: 0,
requiredDVNs: [SuperDVN.address],
optionalDVNs: []
};
const encodedUlnConfig = ethers.utils.defaultAbiCoder.encode(
["tuple(uint64 confirmations, uint8 requiredDVNCount, uint8 optionalDVNCount, uint8 optionalDVNThreshold, address[] requiredDVNs, address[] optionalDVNs)"],
[ulnConfig]
);














Utilization - Liquidity Utilization rate = 24h trading volume / Liquidity
Net APY - annual interest rate
Earned - number of earned EYWA or/and CRV tokens for the whole staking period
EYWA DAO vAPR by Merkl - “EYWA DAO vAPR by Merkl” is distributed separately and can be claimed on the “Farms” page in the “Farming rewards” section or directly in Merkl app. The amount of this yield depends on your veEYWA boost.









































infinity
n/a
n/a
2.8
infinity
1 500 000
3







Access Control: Restricts setAssuranceLockParameters and setMinLockVeEywa calls to the owner of contract(owner()).
Upgradeable via UUPS: Uses UUPSUpgradeable and OwnableUpgradeable patterns, restricting contract upgrades to the owner.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality under the UUPS proxy pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Manages ownership, allowing only the owner to modify critical parameters and authorize upgrades.
ILockHolderV1:
Defines core methods (e.g., boost, deboost, extend) and events for this contract.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Handles secure ERC20 operations for distributing and approving token transfers.
IIncentiveRewardsAggregatorV1: Aggregates lists of reward tokens.
IEscrowVoteManagerV1: Receives gauge emission amounts and coordinates gauge reward distribution.
IEscrowManager: Holds locked token data and checks voting power and freeze logic.
PRECISION: The divisior for percentage math.
s_delegationManager (address)
address of the delegation manager contract.
s_escrowVoteManager (IEscrowVoteManagerV1)
IEscrowVoteManagerV1 interface for the escrow vote manager contract.
s_incentiveRewardsAggregator (IIncentiveRewardsAggregatorV1)
IIncentiveRewardsAggregatorV1 Interface for the incentive rewards aggregator contract.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
Description: Configures ownership, references, and initial state:
References the EYWA NFT, escrow manager, escrow vote manager and delegation manager.
Parameters:
owner_: The address of the contract owner.
delegationManager_: The address of the delegation manager contract.
escrowManager_: The address of the escrow manager contract.
escrowVoteManager_: The address of the escrow vote manager contract.
incentiveRewardsAggregator_: The address of the incentive rewards aggregator contract.
Description:
Function for claim and distributing incentives. The function queries arrays with the addresses of the reward tokens and the size of the reward for each of them on the IncentiveRewardsAggregatorV1 contract Then for each IncentiveRewardsDistributor it claim incentives, calculates on the basis of percentIncentive_ what parts of it should be received by delegator_ and delegatee_ and distributes incentives between them.
Parameters:
delegator_: The delegator's address.
delegatee_: The delegate's address.
percentIncentive_: The percentage of the incentive reward received by the delegate.
Checks:
The function must be called by the DelegationManager contract. Otherwise, UnauthorizedCaller() is thrown.
UnauthorizedCaller()
Thrown when the caller is not authorized to perform the action.
LockHolderV1 contract is an important and necessary part of the lock delegation and self-delegation architecture. It allows for diverse and flexible interaction and integration with all contracts in the system.
uint256 private constant PRECISION = 100_000;constructor() {
_disableInitializers();
}function initialize(
address owner_,
address delegationManager_,
IEscrowManager escrowManager_,
IEscrowVoteManagerV1 escrowVoteManager_,
IIncentiveRewardsAggregatorV1 incentiveRewardsAggregator_
) external initializer;function claimIncentives(
address delegator_,
address delegatee_,
uint256 percentIncentive_
) external;Stable pairs on CrossCurve are designed for correlated assets and aim to maintain a 1:1 transfer ratio between them as closely as possible.
APR - yield in the pool
Total incentives - total rewards allocated for the epoch in USD equivalent
xBTC
$10 000 000
25%
1 489 к
2,08%
xSTABLE
$10 000 000
50%
2 978 к
4,16%
xWETH
$10 000 000
25%
1 489 к
2,08%
To start, in the top right corner click “Connect wallet”, select a suitable wallet from the list and confirm the connection, making sure that you are on the original page app.crosscurve.fi/swap
After successfully connecting, select the required network (twenty one networks available in the CrossCurve pools: Sonic, Fantom, Polygon, BNB Chain, Arbitrum, Optimism, Ethereum, Avalanche, Base, Gnosis, Blast, Fraxtal, Mantle, Linea, Taiko, Mode, Unit Zero, Celo, Kava, Manta, Metis) by clicking the icon next to the wallet address.
The interface consist of basic elements, such as:
Wallet section
If you click on this section pop-up window will appear:
Here you can change network, copy wallet address, see your native token balance in the chosen network, go to transaction history, and disconnect your wallet.
Transaction History
Here you can see status of your transactions, if your transaction has failed the icon will have red mark.
Transaction history can be viewed in the log. By clicking on Details, links to the network scanner where the transaction was made will appear, providing detailed on-chain information.
New tokens available today
Open the New Tokens Today tab and see the full list of recently added supported tokens and their networks.
Earn bonus points
Open the Earn Bonus Points tab and browse currently active trading competitions and/or user reward programs to earn additional points.
Slippage settings.
In the settings, you can specify slippage (by default, the parameter is set at 0.5%) Slippage is a change in price caused by external market movements and not related to the user's activity in the pool. Slippage highly depends on the liquidity volume inside the pool. If a token pool has low liquidity, significant rate changes within the pool require less market movement.
CrossCurve users can configure the maximum permissible slippage for cross-chain operation (details here):
Source and destination input.
Here you can change network and token.
When you click on source/destination input, then Chains/Token menu opens.
Status tracking: displays proposals categorized by active, completed, and pending, along with their outcomes.
To begin interacting with proposals in the CrossCurve app, visit the Proposals page at https://app.crosscurve.fi/proposal under DAO → Vote, then click Connect wallet.
The Proposals page lists DAO proposals, each showing:
Proposal title and a brief summary
Current status:
- Pending voting start
- Proposal approved
- Proposal rejected
- Insufficient quorum
- Active voting
- - Link to the proposal author
- - Date of creation
Voting progress is shown in the status bar, displaying:
Number of votes For and Against
Required quorum in veEYWA tokens
For detailed information, navigate to the specific Proposal page.
To participate in voting, connect your wallet by clicking Connect wallet
If the Proposal status is , the required quorum and voting start time will be shown.
If the Proposal status is , current voting progress will be displayed Yes or No.
After voting, await voting completion.
Once voting concludes, results are shown clearly:
- Proposal approved, with a vote weight of 64% Yes
- Proposal rejected, with a vote weight of 74% No
- Insufficient quorum achieved
Obtain the synthetic token for this direction, in this case, sUSDC_arb.
For USD pools, acquire xfrxUSD tokens. For example, deposit an equal amount of frxUSD and scUSD into the CrossCurve frxUSD pool.
Deposit the universal token and the directional (synthetic) token into the paired pool.
Let's examine each step:
To obtain the LP token xfrxUSD, you need to provide liquidity in the CrossCurve frxUSD pool: https://curve.finance/dex/sonic/pools/factory-stable-ng-25/deposit/.
Go to the CrossCurve frxUSD pool page and connect your wallet.
Enter the desired deposit amount on the Deposit tab. To avoid losses due to slippage, it’s recommended to deposit funds in a balanced manner by clicking Add all coins in a balanced proportion (learn more here).
In the first transaction, confirm the spending of funds by clicking Approve Spending and signing the transaction in your wallet.
In the second transaction, deposit the funds by clicking Deposit and signing the transaction in your wallet.
After the transaction is successfully confirmed on-chain, your wallet will display the amount of received xfrxUSD LP tokens.
If your wallet doesn’t support automatic token addition, add it manually as a custom token with the contract address 0xf1232a1ab5661abdd6e02c6d8ac9940a23bb0b84 on the Sonic network.
sUSDC_arb tokens on the Sonic network can be swapped from any available asset in the xsArbitrum pool via the CrossCurve app.
Navigate to the Liquidity tab in the Yield section. Select the Balanced mode and click Next.
Enter the desired amount to swap, approve the spending by clicking Approve, and sign the transaction in your wallet.
Click Swap to execute the exchange and confirm the transaction in your wallet.
If you know the swap direction, the exchange can be performed in the Trade tab using Advanced mode with any available asset.
Note: Some directions may experience high slippage!
Navigate to the CrossCurve Stable ARB pool page: https://curve.finance/dex/sonic/pools/factory-stable-ng-73/deposit/ and connect your wallet.
Enter the desired deposit amount in the Deposit tab. To avoid losses due to slippage, it’s recommended to deposit using the balanced method by clicking Add all coins in a balanced proportion (more details here).
In the first transaction, approve the spending by clicking Approve Spending and sign the transaction in your wallet.
In the second transaction, deposit the funds by clicking Deposit and sign the transaction in your wallet.
After the transaction is confirmed on-chain, the amount of received xsArbitrum LP tokens will appear in your wallet and in the Your Details tab.
If your wallet doesn’t automatically add the token, manually add it as a custom token using the contract address 0x440bcab62d629ba60ca56b80e565636e0c404e60 on the Sonic network.
Decoding calldata to separate out function-specific parameters from overhead bytes (e.g., selectors).
Validating slicing operations to prevent out-of-bounds data reads.
UUPSUpgradeable (OpenZeppelin): Provides functions for upgrading this contract in a UUPS proxy setup, ensuring only the owner can authorize upgrades.
OwnableUpgradeable (OpenZeppelin): Implements ownership-related logic, allowing only the contract owner to perform certain actions.
ICalldataHelperV1:
Declares the initialize and decode functions, as well as the InvalidSliceParameters error.
This contract does not introduce new constants besides those inherited or implied from the interface. It also does not maintain any additional state variables beyond upgradeability and ownership structures provided by OpenZeppelin libraries.
Description:
Disables initializers to ensure this upgradeable contract cannot be re-initialized after deployment, following best practices for UUPS proxy pattern.
Description:
Initializes the contract in an upgradeable context.
Sets up ownership by transferring ownership to the specified owner_.
Can only be called once due to the initializer modifier from OpenZeppelin.
Parameters:
owner_: The address of the contract owner.
Effects:
Calls __UUPSUpgradeable_init() and __Ownable_init(owner_), configuring the contract for UUPS upgradeability and ownership management.
Description:
Decodes the provided calldata to extract three main elements:
m_calldata: The method-specific or function-specific bytes of calldata.
m_target: The address the calldata is meant to target.
m_chainId: The chain identifier for cross-chain or multi-chain scenarios.
Skips the first 4 bytes, typically used as a selector or prefix.
Parameters:
calldata_: The full calldata to decode, where the first 4 bytes are not part of the relevant data for extraction.
Return:
m_calldata: The extracted method calldata (bytes).
m_target: The extracted target address (address).
Logic:
Calls the private _slice function to remove the first 4 bytes.
Uses abi.decode(...) with a tuple (bytes, address, uint64, address) to decode the relevant fields (although the last address is ignored in this particular decode pattern).
Description:
Restricts contract upgrades so that only the owner may authorize them, protecting upgrade logic from unauthorized calls.
Description:
Extracts a slice from data_ starting at offset start_ for length_ bytes.
Reverts with InvalidSliceParameters if out-of-bounds.
Used internally by decode to remove the first 4 bytes (or any other arbitrary slice).
Parameters:
data_: The original bytes array to slice.
start_: The offset in data_ to begin slicing.
Return:
result_: A newly allocated bytes array of size length_, containing the requested slice.
Errors:
InvalidSliceParameters(): Thrown if start_ + length_ exceeds the length of data_.
Description:
Indicates that the requested slice exceeds the bounds of the original array (start_ + length_ > data_.length).
CalldataHelperV1 provides a lightweight, upgradeable solution for parsing transaction calldata and extracting specific parameters like function-specific calldata, target addresses, and chain IDs. It integrates with standard libraries for safe upgradeability (UUPSUpgradeable) and ownership control (OwnableUpgradeable), ensuring secure and maintainable deployment. By strictly enforcing slice parameter checks and skipping the initial 4 bytes, CalldataHelperV1 simplifies the process of handling custom-encoded transaction data in cross-chain or proxied contexts.
To start using the CrossCurve application, navigate to the Vote page under the DAO section. Click «Connect wallet», select your wallet from the list, and confirm the connection, ensuring you are on the official page: https://app.crosscurve.fi/vote-pools
After successfully connecting your wallet, open the Pools tab to participate in pool voting.
You will see the following details:
Current voting round ends in - Countdown timer indicating when the current voting round concludes
Total voting power available for this epoch - Combined voting power of all DAO participants for the current epoch
You have - Number of your locks and their voting power in veEYWA tokens
Voted - Number of your locks and the total veEYWA voting power you have already allocated this epoch
Ready for voting - Number of locks available for voting and their total veEYWA voting power
Estimated EYWA emission in the next epoch - Estimated EYWA token rewards allocated for the upcoming epoch
Estimated CRV emission in the next epoch - Estimated CRV token rewards allocated for the upcoming epoch
Estimated incentives available in the current epoch - Estimated incentives from partners allocated in the current epoch (in USD equivalent)
In the window displaying participating voting pools, the following information appears:
Pools - Pool name and type (Stable pool**, Volatility pool*)
Chain - Network of the pool
Incentives - Amount of incentives allocated for votes on each pool during the current epoch
vAPR - Projected yield metric for the next epoch, calculated based on current pool votes and TVL
Select % vote - Select the percentage of your voting power allocated to the chosen pool
Votes sent - Percentage of voting power you have already allocated to each pool
Est. rewards - Estimated reward amount in USD equivalent
CrossCurve offers two distinct liquidity pools to users: the Stable Pool and the Volatility Pool:
* Volatility Pools consist of liquidity (Curve pools) for asset pairs with volatile prices, typically experiencing divergence. For example, USDT vs. EYWA or ETH vs. BTC. Volatile pairs are formed by combining uncorrelated assets and utilize Curve's unique impermanent loss compensation mechanism for pools containing volatile assets. ** Stable Pools are pools of stable liquidity (Curve pools) between assets whose prices are pegged to each other. For example, USDT vs. USDC.
Another case involves derivative assets, such as wstETH and rETH. Although rETH is considered a volatile asset, the trading pair between wstETH and rETH is classified as a stable pool because the price of wstETH does not significantly fluctuate relative to rETH.
Stable pairs on CrossCurve are designed for correlated assets and aim to maintain a 1:1 transfer ratio between them as closely as possible.
To participate in voting, select the pool you're interested in, adjust the percentage of your voting power to allocate, and click Vote. Then, sign the transaction in your wallet.
The total of your votes across all pools must equal 100% for the Vote button to become active.
You can view detailed information about your submitted votes by expanding the Votes sent menu.
To cancel your current vote for a specific pool, click Reset. To remove all your votes across all pools, click Reset all.
When confirming vote cancellation, all your votes for the selected pool will be withdrawn. To proceed, click Ok and sign the transaction in your wallet.
Access Control: Only the escrow vote manager can call createRewardsDistributor, preventing unauthorized distribution contract creation.
Upgradeable via UUPS: Ensures the factory contract can be upgraded over time, with ownership-based control on upgrades.
By implementing IRewardsDistributorFactoryV1, RewardsDistributorFactoryV1 provides a standard interface for deployment logic and event transparency (though no new custom events are declared here beyond the interface's contract structure).
UUPSUpgradeable (OpenZeppelin): Provides the upgrade mechanism under the UUPS proxy standard, restricting upgrades to the contract owner.
OwnableUpgradeable (OpenZeppelin): Establishes ownership logic, allowing the owner to authorize upgrades and potentially modify other aspects of the factory (not used extensively here but available if needed).
IRewardsDistributorFactoryV1:
Declares the initialize and createRewardsDistributor functions, along with an InvalidCaller error.
Additional External References:
IncentiveRewardsDistributor: The contract being deployed by this factory. It manages incentive reward distributions for an escrow manager and is constructed with references to the escrow vote manager and escrow manager.
s_escrowVoteManager (address):
The address of the escrow vote manager contract. Only this address may invoke createRewardsDistributor on the factory.
Description:
Disables contract initializers to ensure initialize() can only be called once. A standard pattern for UUPS upgradeable contracts.
Description:
Configures the factory contract by assigning ownership (owner_) and storing the escrow vote manager address. This function can be called only once due to the initializer modifier.
Parameters:
owner_: The address to be assigned as the owner of this factory contract.
escrowVoteManager_: The address of the escrow vote manager responsible for orchestrating new distributor creations.
Logic and Effects:
Invokes __UUPSUpgradeable_init() and __Ownable_init(owner_) for upgrade and ownership setup.
Sets s_escrowVoteManager = escrowVoteManager_.
Description:
Creates and returns a new IncentiveRewardsDistributor contract instance, linking it to the calling escrow vote manager (msg.sender) and the provided escrowManager_. The call reverts if not invoked by s_escrowVoteManager.
Checks:
Must be called by s_escrowVoteManager. Otherwise, it reverts with InvalidCaller().
Logic:
If msg.sender != s_escrowVoteManager, revert with InvalidCaller().
Deploys a new IncentiveRewardsDistributor by calling its constructor:
Return:
address: The address of the newly created incentive rewards distributor contract.
Description: Restricts upgrades of this factory to the contract’s owner, following the UUPS standard. This ensures that only the owner can deploy a new logic implementation for this factory contract.
InvalidCaller()
Thrown if createRewardsDistributor is called by an address other than s_escrowVoteManager.
RewardsDistributorFactoryV1 provides a straightforward pattern for creating new IncentiveRewardsDistributor instances. By restricting calls to its createRewardsDistributor function to the escrow vote manager, it ensures that only authorized processes can spin up new distributor contracts. Coupled with UUPS upgradeability, the factory is future-proofed, allowing for modifications to how distributors are instantiated if the protocol’s requirements evolve over time.
Custody of Funds: Holds ERC20 tokens and ETH in a secure manner.
Restricted Withdrawals: Only the contract’s owner can withdraw funds, specifying the token address, amount, and recipient.
Non-Reentrant Calls: Uses ReentrancyGuard to prevent complex re-entrancy exploits during withdrawals.
By implementing the ITreasury interface, Treasury provides a standardized API (the withdraw function) and emits an event (TokenWithdrawn) whenever funds are moved out.
Ownable (OpenZeppelin)
Allows the contract to have an owner who can perform restricted operations. In this case, only the owner can call withdraw.
ReentrancyGuard (OpenZeppelin)
Protects critical functions from re-entrancy attacks. The withdraw function uses the nonReentrant modifier.
ITreasury (Custom Interface)
Declares the withdraw function signature and TokenWithdrawn event. The contract implements these specifications.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Used to safely transfer ERC20 tokens in the withdraw function.
Address (OpenZeppelin): Provides the sendValue method for securely transferring ETH.
The Treasury contract does not introduce mutable storage variables beyond those inherited from its parent classes. However, it defines:
owner (Ownable.sol)
A variable inherited from Ownable indicating the contract owner. Managed internally by the Ownable library’s _owner storage variable.
No other custom state variables are defined. The contract relies on the OpenZeppelin libraries for ownership tracking and reentrancy control.
Description:
The constructor takes a single parameter, owner_, which designates the address to be assigned as the contract owner via Ownable. This ownership implies exclusive access to withdraw.
Parameters:
owner_: The address that will be granted ownership of the contract upon deployment.
Effects:
Calls Ownable(owner_) constructor to set the provided owner_ as the owner.
No additional logic is performed here.
Description:
A receive fallback function that allows the contract to accept native ETH transfers (e.g., via send or transfer with no calldata). This function does not store or otherwise process the ETH, aside from receiving it into the contract’s balance.
Description:
Allows the contract owner to withdraw either an ERC20 token or native ETH from the treasury to a specified recipient_. If token_ is the zero address (address(0)), it indicates a withdrawal of ETH. Otherwise, it withdraws the specified ERC20 token using a safe transfer.
Parameters:
token_: The address of the ERC20 token to withdraw. If address(0), the function sends ETH instead of tokens.
amount_: The amount of tokens (or ETH) to withdraw.
recipient_: The address that will receive the withdrawn tokens or ETH.
Checks & Effects:
The function uses onlyOwner to ensure only the contract’s owner can invoke it.
Uses nonReentrant from ReentrancyGuard to prevent nested re-entrant calls.
Events:
Emits TokenWithdrawn(token_, amount_, recipient_) upon a successful withdrawal, logging details for transparency.
Emitted When:
The withdraw function completes successfully, whether removing ETH or ERC20 tokens.
Parameters:
token: The address of the token being withdrawn. Zero address if ETH.
amount: The quantity of tokens or ETH withdrawn.
recipient: The address that received the withdrawn funds.
Treasury acts as a straightforward contract for securely holding and releasing ETH or ERC20 tokens under the CrossCurve ecosystem. With Ownable restricting withdraw calls to the contract owner and ReentrancyGuard ensuring robust security, the Treasury provides a trustworthy store for tokens:
Secure Custody: Only an authorized owner can move assets out.
Versatile Withdrawals: Supports both ETH and arbitrary ERC20 tokens using standardized SafeERC20 operations.
Transparent Logging: The TokenWithdrawn event ensures on-chain traceability of funds outflow.
This minimal approach ensures clarity, security, and traceable control over treasury assets within the CrossCurve framework.













Open , and enter the wallet address that received the vesting safe in the search bar, or enter the link in the format {wallet address}, replacing {wallet address} with your wallet address.
In the list of , filter by the “Claim” function under Method.
In the filtered list, find the claim transaction. To locate the safe addresses, open Transaction Details by clicking on the chosen transaction.
Find the safe address in the Transaction Action or ERC-20 Tokens Transferred, checking the amount of EYWA tokens in that safe.
To copy the safe address, click on it and copy it to your clipboard.
Make sure you remember the address(es) of the safe(s) that you plan to deposit into the .
Go to the EYWA Locker contract page: 0xdCa5d16ac3708658ECc971d3AeE5d5CD6e5E1faD , choose and connect your wallet by clicking
Expand the 5t line, createLock, and fill in the fields:
lockDuration_(unit256) - the lock duration in seconds
recipient_(address) - the wallet address of the lock’s owner (it’s important that you have access to this wallet)
vestingWallets_(address[]) - the array of safe addresses*
After the filling in the required fields, click the button and sign the transaction in your wallet.
Once the transaction is successfully processed on-chain, you will receive an EYWA DAO NFT in your wallet.
To later boost your votes, remember the ID (EYWA DAO NFT ID) of the created lock.
Go to your wallet page and expand the TOKEN HOLDINGS list in the Overview tab.
Find the EYWA DAO NFT you received after creating the lock and open its token page.
Find your EYWA DAO NFT ID in the transaction list under the Item column or on the Transaction Details page in the ERC-721 Tokens Transferred section.
To receive a boost, you must have the EYWA DAO NFT on the same address that you created the lock from, and you must know its ID.
Go to the EYWA NFT contract address 0x33b98A477512A34Af0D311DA5F59FC5341693962 page: and confirm the lock for this NFT in the contract.
Select and then click
Expand the “approve” first line and fill in the fields:
to - address of the Locker contract 0xdca5d16ac3708658ecc971d3aee5d5cd6e5e1fad
tokenid(unit256) - The ID of the NFT to receive the boost. (If you need boosts for multiple NFTs, repeat this operation for each NFT)
Go the the EYWA Locker contract address page 0xdca5d16ac3708658ecc971d3aee5d5cd6e5e1fad
Select then clickand connect your wallet by pressing
Expand the “boost” second line and fill in the fields:
tokenid_(unit256) - The ID of the lock (EYWA DAO NFT ID), to be boosted.
collectionTokenIds_(unit256) - the ID(s) of the NFT(s), that will provide the voting boost (If you have only one NFT, enter [id]. For multiple NFTs, [id1, id2], and so on).
After entering the information, click the button and sign the transaction in your wallet. To see your updated voting power, go to the interface.
The Eywa NFT collection includes 53 996 unique NFTs. Their number diminishes as they are merged.
The collection represents four mythical characters: Magician, Dryad, Ant, and Spider. EYWA NFTs are an example of generative art where each character features randomized attributes that grant it uniqueness.
Curve inflation is directed to EYWA pools on Convex, and now liquidity providers receive incentives in CRV
For example, the yield in the is currently as follows:
Base Curve vAPR: 2.69%
CRV vAPR (incl. 2.5x boost): 212.07%
Total vAPR: 214.76%
GaugeFactoryV1 is an upgradeable factory contract responsible for deploying and initializing Gauge contracts within the CrossCurve ecosystem. These gauges are used to manage and distribute rewards for various liquidity pools or other vote-driven incentives. The factory integrates with an Escrow Vote Manager to ensure that only the authorized vote manager can create new gauges, thus maintaining a secure and controlled environment for gauge deployments.
Key Roles and Features:
constructor() {
_disableInitializers();
}function initialize(address owner_) external initializerfunction decode(bytes calldata calldata_) external pure returns (
bytes memory m_calldata,
address m_target,
uint64 m_chainId
)function _authorizeUpgrade(address) internal override onlyOwnerfunction _slice(
bytes memory data_,
uint256 start_,
uint256 length_
) private pure returns (bytes memory result_)address public s_escrowVoteManager;constructor() {
_disableInitializers();
}function initialize(address owner_, address escrowVoteManager_) external initializerfunction createRewardsDistributor(address escrowManager_) external returns (address)function _authorizeUpgrade(address) internal override onlyOwnerconstructor(address owner_) Ownable(owner_) {}receive() external payable {}function withdraw(
address token_,
uint256 amount_,
address recipient_
)
external
onlyOwner
nonReentrant0x7ce8aF75A9180B602445bE230860DDcb4cAc3E42m_chainId: The extracted chain identifier (uint64).
length_: Number of bytes to copy into the new array.token_ == address(0), uses Address.sendValue to send amount_ of ETH to recipient_.Otherwise, calls safeTransfer on IERC20(token_) to transfer amount_ tokens to recipient_.




















new IncentiveRewardsDistributor(msg.sender, escrowManager_)The characters in the collection are unique creations, drawing inspiration from beloved science fiction universes.
The Magician Crafted from leaves and various flora types, the magician is inspired by the Star Wars universe and Elemental creatures, as well as ancient Roman and Greek mythology.
The Dryad This character is inspired by ancient Greek myths, aliens, and the golden era of science fiction, presenting a stunning fusion of a wood nymph with a World of Warcraft (WoW) hero.
The Ent Assembled from tree bark and roots, the Ent is inspired by the Ents from the Lord of the Rings (LOTR) universe, Swamp Thing from DC Comics, and Groot from Marvel.
The Spider The spider character embodies an aggressive, dynamic figure, combining an arachnid with a trickster — a mix of Baal from Diablo II, Monsters, Inc., and other characters, infused with elements of insects and alien life forms.
We have deliberately directed our design team to embrace a “fairytale” aesthetic in the creation of our characters' likenesses. Regardless of age, we all cherish a touch of magic in our lives.
Echoing the words of Steve Jobs: “Follow your heart, stay hungry, stay foolish!” we are committed to developing the finest cross-chain product on the market. Thank you for your support!
The collection is broken down into five levels of rarity: Common, Uncommon, Rare, Legendary, and Infinity. The rarest of all are the Magician Infinity NFTs, of which there are only 193 in the entire EYWA NFT collection.
Currently, the collection is available on the Aurora and Arbitrum networks:
On the Aurora network, the collection is available for trading within our Telegram communities (Links to Telegram chats for trading Eywa NFTs: English speaking region CIS region).
On the Arbitrum network, the collection is available for trading on OpenSea.
The EYWA NFT collection is composed of ERC-721 tokens with the following unique functions:
• Container function for storing up to 1 500 000 EYWA tokens
• Merge function that allows you to increase the size of the container and the rarity of the NFT by combining multiple NFTs of one level into one rarer NFT
• CrossCurve DAO vote multiplier function via veEYWA
Each NFT in the collection functions as a container for EYWA tokens. You can attach both unlocked and locked (in vesting safes*) tokens to the NFT. This allows the user to sell blocked EYWA tokens at any time.
The capacity of each NFT is the maximum number of EYWA tokens it can contain and depends on the rarity of the NFT. The highest capacity — 1 500 000 EYWA — is reserved for the Infinity rarity level NFTs. In the Aurora chain, you can see your current balance of token in the container. Once migrated to the Arbitrum chain, the tokens will be separated from the NFT and can be received as vesting safes via the Claim portal after the TGE.
For details, see the table below:
common
500
uncommon
3 000
rare
25 000
legendary
250 000
infinity
1 500 000
Several NFTs of the same type can be merged to create a single NFT with a higher rarity level. This will also merge all of the tokens contained in the source NFTs.
Multiplier table for NFT merging:
common
5
1 uncommon
uncommon
7
1 rare
rare
9
1 legendary
legendary
n/a
To vote in the EYWA DAO, users must lock EYWA tokens — the longer the lock period, the more voting power the user gets. Using EYWA NFTs can also increase voting power. Each NFT can increase the number of available votes by the maximum number of tokens it can contain.
For details, see the table below:
common
500
1.006
uncommon
3 000
1.036
rare
25 000
1.3
legendary
250 000
After the NFT collection is migrated to the Arbitrum chain, all of the above functions will become available. Before the TGE, we will open up a bridge to move the NFTs from Aurora to Arbitrum, as well as the NFT Manager to fully engage with all of the functions of the NFTs.
The NFT Manager will ensure access to tokens contained in the NFTs, which will be separated from their containers after the migration to Arbitrum and be put together in each user’s wallet. Users will be able to put tokens into vesting safes and keep rEYWA in the NFTs.
You can purchase the EYWA token on CEX or DEX. The list of available exchanges can be viewed here: https://www.coingecko.com/en/coins/eywa
Let’s consider an example of purchasing the EYWA token with USDT on the CrossCurve DEX.
EYWA tokens can be purchased on CrossCurve for any assets available in the app (USDT, USDC, crvUSD, DAI, ETH, BTC etc.)
Attention! Be aware of possible high slippage before making an exchange to avoid loss of funds.
To purchase EYWA with USDT, you need to have USDT in your wallet on the Arbitrum network and ETH in the Arbitrum network to pay for transaction gas in Gwei (gas cost can be checked here - https://arbitrum.blockscout.com/gas-tracker).
Go to https://crosscurve.fi and use the quick link Buy EYWA → Buy on CrossCurve and click Connect wallet
Select the wallet installed in your system and confirm the connection to the application in your wallet
After successfully connecting the wallet, the application will direct you to the EYWA - USDT trading pair on the Arbitrum network. Enter the desired amount for exchange and click Approve USDT
Sign the USDT spending transaction in your wallet
To complete the exchange, click Swap
Sign the exchange transaction in your wallet
Wait for the on-chain transaction to complete
Go to the Liquidity page in the Yield section
In the Choose pool list, select EYWAUSDT pool, the Deposit operation, the Easy mode operation type, and click Next
Enter the amount of EYWA tokens and click Approve EYWA
Sign the EYWA spending transaction in your wallet
To complete the transaction, click Swap
Sign the exchange transaction in your wallet
Wait for the on-chain transaction to complete
Go to the Stake page in the Curve section on https://curve.convexfinance.com/stake and connect your wallet
In the Stake Curve LP Tokens section, select Arbitrum One chain, enter EYWA in the Search pools field and the application will display USDT+EYWA pool
Enter the amount of EYWAUSDT LP tokens and click Approve
Sign the EYWAUSDT LP spending transaction in your wallet
To stake EYWAUSDT LP, click Deposit & Stake
Sign the depositing & staking transaction in your wallet
After the on-chain transaction is completed, the provided liquidity will be displayed in the My Deposits field, and the accrued rewards will be displayed in the Claimable field

Access Control: Restricts createGauge calls to the escrow vote manager (s_escrowVoteManager).
Upgradeable via UUPS: Uses UUPSUpgradeable and OwnableUpgradeable patterns, restricting contract upgrades to the owner.
By implementing IGaugeFactoryV1, GaugeFactoryV1 provides a standardized interface and event structure for gauge creation, enabling other contracts in the CrossCurve ecosystem to request new gauges securely.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality using the UUPS proxy pattern. Only the owner can authorize upgrades.
OwnableUpgradeable (OpenZeppelin): Establishes ownership and restricts certain critical functions (like upgrades) to the contract owner.
IGaugeFactoryV1:
Declares functions (initialize and createGauge) and the GaugeCreated event. Also defines the InvalidCaller error.
Additional External References:
ERC1967Proxy (OpenZeppelin): A proxy implementation that stores the logic contract address in storage per EIP-1967.
IDistributionCreator.CampaignParameters: Used to initialize reward distribution parameters for newly created gauges.
GaugeV1: The gauge implementation contract being deployed as a proxy.
s_escrowVoteManager (address):
The address of the escrow vote manager contract authorized to create new gauges. Only s_escrowVoteManager can call the createGauge function.
Description:
Disables initializers to prevent re-initialization in a UUPS upgradeable setup. Ensures the initialize function can only be called once.
Description:
Initializes the factory contract by setting the contract owner (owner_) and the escrow vote manager (escrowVoteManager_). This function can only be called once due to the initializer modifier.
Parameters:
owner_: The address designated as the owner of this factory.
escrowVoteManager_: The address of the authorized escrow vote manager contract.
Effects:
Calls __UUPSUpgradeable_init() to set up the UUPS upgrade mechanism.
Calls __Ownable_init(owner_), assigning ownership to owner_.
Description: Deploys and initializes a new GaugeV1 contract as an ERC1967Proxy, passing in the gauge implementation address, initialization arguments, and returning the newly created gauge address.
Parameters:
owner_: The address that will become the owner of the new gauge contract.
eywa_: The address of the EYWA token the gauge will handle for reward distribution.
campaignParameters_: A struct of parameters (e.g., schedule, amounts) used by the gauge for reward distribution.
Checks:
The caller must be s_escrowVoteManager. Otherwise, InvalidCaller() is thrown.
Logic:
Deploys a new GaugeV1 implementation contract.
Instantiates an ERC1967Proxy pointing to that implementation.
Encodes the constructor arguments (owner, escrow vote manager address, EYWA token address, campaign parameters) for the gauge’s
Return:
address: The newly deployed gauge proxy contract.
Events:
GaugeCreated(m_gauge, m_implementation): Indicates a new gauge contract was created.
Description: Restricts the contract’s upgrade function (in a UUPS proxy context) to the owner, ensuring unauthorized parties cannot upgrade the factory logic.
Emitted When:
A new gauge contract is deployed via createGauge.
Parameters:
gauge: The address of the newly created gauge (proxy).
implementation: The address of the gauge implementation contract used for the new proxy.
Description:
Thrown if createGauge is called by an address other than s_escrowVoteManager. Ensures gauge creation is limited to the authorized escrow vote manager.
GaugeFactoryV1 securely and upgradeably deploys GaugeV1 contracts under the control of the escrow vote manager. By enforcing that only the designated manager can call createGauge, it prevents unauthorized deployments while still allowing flexible, time-extended reward distribution campaigns. The combination of UUPS upgradeability, ownership checks, and a standardized creation event (GaugeCreated) supports a robust, maintainable environment for launching new gauges in the CrossCurve ecosystem.



In order to become a participant in CrossCurve DAO, you need to lock your EYWA tokens or EYWA NFT along with them.
Users can lock EYWA tokens for up to 3 years, receiving veEYWA — their voting power in the DAO. The longer the lock duration and the higher the NFT rarity, the greater the participant’s voting power (influence) in the DAO and the more incentives and benefits they gain.
Voting power decreases as the token unlock time approaches unless the lock is extended. This encourages long-term commitment, strengthens the project’s stability, and allows participants to actively influence its development.
EYWA NFTs multiply veEYWA, increasing voting power, income, and a user's influence in the DAO. To do this, you must attach EYWA tokens or one or more Vesting Safes containing EYWA tokens to an EYWA NFT.
A Vesting Safe is a special contract from the CrossCurve team that stores locked EYWA tokens. The tokens in the safe unlock according to an algorithm matching the type of round in which they were received.
The Locker is a smart contract where owners lock their EYWA tokens for various durations. The purpose of locking is to obtain voting power in the form of veEYWA. Voting power depends on the lock duration: the longer the lock, the greater the voting power for the same number of locked tokens.
Maximum lock duration: 3 years (156 weeks), providing the maximum ratio: 1 locked token = 1 vote.
Minimum lock duration: a few days (until the end of the current epoch). For example, 2 days give 2/1092 of a vote.
Example: 156 tokens locked for one week give 1 vote.
Where T is the lock time in weeks (Formula 1)
When working with the smart contract, note that the contract automatically "rounds" the submitted lock date to the end of the previous epoch (Thursday 00:00 UTC). This means that if a date falls on a Friday, Saturday or Monday, the smart contract will set the lock time to the preceding Thursday.
To accommodate this behavior, the website interface for interacting with the sends a especially calculated date, to the smart contract:
where:
- the current time,
- time remaining until the end of the current epoch,
- the duration of one epoch (1 week),
n - the number of weeks the user wants to lock tokens.
Additionally, the total lock time cannot exceed 156 epochs (weeks).
Due to these mechanics, achieving a value equal to 1 is nearly impossible. The closest approximation can only occur if a locking transaction is sent for 156 weeks immediately after the start of a new epoch, such as Thursday at 00:00:01 UTC. In that case:
However, time constantly moves forward, and even a minute later:
Whether or not to continuously update the lock time, and at what intervals, is a decision each DAO participant must make individually based on their own objectives and intentions.
Where:
is the number of tokens locked by the owner i, considering NFT boosts,
is the lock-time coefficient for user i,
n is the number of users who have locked their EYWA tokens
(Formula 2)
EYWA DAO NFT is an ERC-721 NFT created when EYWA tokens are locked in the .
Key features:
Attaching assets: Each EYWA DAO NFT can have EYWA tokens, Vesting Safes, and other EYWA NFTs attached to it.
Obtaining veEYWA: The obtained veEYWA is automatically tired to the corresponding EYWA DAO NFT.
Multiple ownership: A user can own an unlimited number of EYWA DAO NFT.
Summation of veEYWA: The total amount of a user’s veEYWA is equal to the sum of the veEYWA of all their EYWA DAO NFTs.
Thus, EYWA DAO NFT serves as a hub for managing your locked assets and voting power in the DAO, providing flexibility and scalability in project governance.
When creating an EYWA DAO NFT in the Locker, you can lock EYWA tokens in various states When transferring to the Locker:
EYWA tokens (standard ERC-20)
Ownership is transferred to the contract.
Vesting Safe contracts with direct ownership (held in the user’s wallet)
Ownership of the Vesting Safe contract is transferred to the Locker.
Vesting Safe contracts with ownership via an NFT (Vesting Safe contracts attached to an EYWA NFT)
The Vesting Safe is detached from an EYWA NFT and transferred to the Locker.
The EYWA NFT ownership is also transferred to the Locker.
ERC-20 EYWA tokens with ownership via an NFT (EYWA tokens attached to an EYWA NFT)
Tokens are detached from an EYWA NFT and transferred to the Locker.
Ownership of an EYWA NFT is also transferred to the Locker.
The calculates the amount of veEYWA based on the total number of EYWA tokens locked, including both standard ERC-20 tokens and those in the Vesting Safe.
You cannot create an EYWA DAO NFT by adding an empty EYWA NFT to the Locker.
You can attach no more than 100 Vesting Safes and 100 EYWA NFTs to one EYWA DAO NFT.
You can modify an EYWA DAO NFT in several ways:
Adding additional EYWA tokens:
You can lock more EYWA tokens in any of the ways described above at the time of creating an EYWA DAO NFT.
Adding/attaching empty EYWA NFTs:
You can attach additional empty EYWA NFTs to an existing EYWA DAO NFT.
Removing/detaching EYWA NFTs:
You can detach an EYWA NFT from an EYWA DAO NFT, returning them to the user’s ownership.
Extending the lock duration of tokens:
You can extend the lock duration of already locked EYWA tokens to increase voting power.
EYWA NFT Collection
A released collection EYWA NFTs allows users to increase their voting power in the DAO. To do this, you must attach your NFTs from this collection in the. When sending NFT tokens, they are locked under different conditions than standard EYWA tokens.
Attaching and Detaching EYWA NFTs
Attaching EYWA NFTs:
When one or more EYWA NFTs are added to an EYWA DAO NFT, a boost is applied to the locked EYWA tokens, increasing voting power.
Detaching EYWA NFTs:
MV (Multiplier for veEYWA): A multiplier that increases veEYWA.
CT (Capacity per NFT): The maximum number of EYWA tokens affected by an NFT.
total number of tokens locked by the owner
number of tokens of the same rarity locked by the owner
- this is the total number of tokens that can be affected by NFT boosts (Formula 3)
If is greater than or equal to , then the overall boost formula is:
(Formula 4)
If is greater than , it means the volume of tokens that could theoretically be influenced by the NFT boost is greater than the owner’s tokens. Therefore, we must fairly allocate the available token volume for the greatest results. For that, we use the following algorithm:
=*1500000
If is less than or equal to , then = *3;
Else: = *3; =-
=*250000
The final is then used to determine the amount of veEYWA votes owned by the token holder.
Example: 1 000 000 tokens and one Legendary NFT are locked (=1). Using the Formula 3: =0*500+ 0*3000+0*25000+1*250000+0*1500000 = 250000
Since is greater than , we shall use the Formula 4:=1000000-250000+0*500*1.006+ 0*3000*1.036++0*25000*1.3+1*250000*2.8+0*1500000*3 = 750000+700000=1450000
Example. 1 000 000 tokens and ten Legendary NFTs are locked (=10). Using the Formula 3: =0*500+ 0*3000+0*25000+10*250000+0*1500000 = 2500000
Since is less than , we cannot use the Formula 4. Therefore, we shall use the following algorithm:
==1 000 000
=*1500000=0
is greater than , therefore
= *3=0; =- = 1 000 000
=*250000 = 10* 250 000 = 2 500 000
If is less than or equal to , therefore the final calculations are equal to: =+ *2.8 = 0+1 000 000 *2.8 = 2 800 000
Example. 2 000 000 tokens,1 Infinity NFT ( =1) and 10 Legendary NFTs are locked(=10). Using the Formula 3, we get: =0*500+ 0*3000+0*25000+10*250000+1*1500000 = 4 000 000
Since is less than , we cannot use the Formula 4. Therefore, we shall use the following algorithm:
==2 000 000
=*1500000 =1*1 500 000
is greater than , therefore
= *3=4 500 000; =-=2 000 000 -1 500 000 = 500 000
=*250000=10*250 000 = 2 500 000
is less than , therefore the final calculations are equal to: =+ *2.8=4 500 000 + 500 000*2.8 = 5 200 000
The CrossCurve protocol provides a unique system that allows reaching a maximum number of votes — 2 820 221 429. This figure is achieved through a combination of EYWA tokens and NFT multipliers, as well as their optimal distribution according to capacity.
In the new version of our NFT collection, a “freeze” mechanism has been introduced. After detaching tokens from an NFT, a 4-hour period is activated during which the NFT cannot be moved. This prevents the aforementioned unscrupulous practice: if a user attempts to detach tokens from an NFT being sold. They cannot finalize the deal since the NFT cannot be transferred to the buyer. As a result, only buyers who possess tokens will be able to purchase the NFT, reducing the risk of front-running.
Furthermore, the mechanism also applied to cases where tokens are locked in the DAO Locker. This means that when locking an NFT in the Locker, the same 4-hour “freeze” applies. This delay is necessary to ensure the system’s security and prevent abuse. Users should keep this feature in mind to avoid misunderstandings. It’s important to plan NFT-related actions with a “freeze” period in mind.
To provide liquidity in the or pool on the Taiko network, you need to obtain or LP tokens. These LP tokens consist of two assets: the stablecoin and the synthetic derivative, or and , respectively.
Since the CrossCurve Stable and CrossCurve WETH pools have migrated from the Sonic network to the Taiko network, you need to acquire the assets on the new network in order to receive the LP tokens.
GaugeV1 is an upgradeable contract used to manage reward distributions for a particular pool or strategy in the CrossCurve ecosystem. The contract primarily integrates with the Escrow Vote Manager (s_escrowVoteManager) to authorize reward notifications and uses a Distribution Creator (DISTRIBUTION_CREATOR) for executing reward distribution campaigns.
Key features include:
address public s_escrowVoteManager;constructor() {
_disableInitializers();
}function initialize(address owner_, address escrowVoteManager_) external initializerfunction createGauge(
address owner_,
address eywa_,
IDistributionCreator.CampaignParameters calldata campaignParameters_
)
external
returns (address)function _authorizeUpgrade(address) internal override onlyOwnerSets s_escrowVoteManager to escrowVoteManager_.
initializeEmits the GaugeCreated event with the new gauge’s proxy address and the gauge implementation address.


n/a
infinity
n/a
n/a
2.8
infinity
1 500 000
3
If an EYWA DAO NFT did not participate in pool voting in the current epoch:
EYWA NFTs can be attached at any time.
If an EYWA DAO NFT participated in pool voting in the current epoch:
The attached EYWA NFTs involved in voting cannot be detached
To detach them, you must cancel the vote for the pools.
Infinity
3
1 500 000
If is less than or equal to , then: =+ *2.8;
Else: = + ; =-
=*25000
If is less than or equal to , then =+ *1.3;
Else: = + ; =-
=n*3000
If is less than or equal to , then =+ *1.036;
Else: = + ; =-
=*500
The overall results are equal to =+ *1.006
Common
1,006
500
Uncommon
1,036
3 000
Rare
1,3
25 000
Legendary
2,8
250 000
If you hold xsTaiko LP tokens on the Sonic network, you need to go to the pool page: https://www.curve.finance/dex/sonic/pools/factory-stable-ng-78/withdraw/ and perform a Withdraw of the LP tokens, receiving xfrxUSD and s2Pool_t for the CrossCurve Stable TAI pool.
We recommend performing the Withdraw in Balanced mode to reduce loss risk due to slippage.
The xfrxUSD and s2Pool_t tokens from the xsTaiko pool on the Sonic network can be exchanged for USDC and sxfrxUSD_s on the Taiko network, respectively:
Go to the Liquidity tab in the Yield section on the xsTaiko pool page: https://app.crosscurve.fi/liquidity?pool=0xedcf9ef9b389a8f52e81958d8212faf6fbd758ae&type=curve&action=withdraw&input=0x54f0055f387e7dcbfa060eaed81ea8bf1f6c808f&output=0x07d83526730c7438048d55a4fc0b850e2aab6f0b&chainIn=146&chainOut=167000
Select the Withdraw action in Balanced mode and click Next.
Enter the amount of s2Pool_t tokens and perform the Swap to USDC.
Go to the Liquidity tab in the Yield section on the xsoTaiko pool page: https://app.crosscurve.fi/liquidity?pool=0xa17aa5ee656849221c8d9d062894e1145cbda864&type=curve&action=deposit&input=0xf1232a1ab5661abdd6e02c6d8ac9940a23bb0b84&output=0xb1712abdaf3f2959c0d5063e827ddb8183145f11&chainIn=146&chainOut=167000
Select the Deposit action in Balanced mode and click Next.
Enter the amount of xfrxUSD tokens and perform the Swap to sxfrxUSD_s.
If you hold xeTaiko LP tokens on the Sonic network, you need to go to the pool page: https://www.curve.finance/dex/sonic/pools/factory-stable-ng-99/withdraw/ and perform a Withdraw of the LP tokens to receive xfrxETH and sWETH_t for the CrossCurve WETH TAI pool.
We recommend using the Balanced mode when withdrawing to minimize losses due to slippage.
xfrxETH and sWETH_t tokens from the xeTaiko pool on the Sonic network can be exchanged for sxfrxETH_s and WETH on the Taiko network respectively: Go to the Liquidity tab in the Yield section on the xeTaiko pool page: https://app.crosscurve.fi/liquidity?pool=0x6d9f0ff2b7f1397ee731f6370d8e4699ffad7bc5&type=curve&action=withdraw&input=0x8af98914c95a3ec6e790d79e9ef9072e307fc086&output=0xa51894664a773981c6c112c43ce576f315d5b1b6&chainIn=146&chainOut=167000 Select the Withdraw action in Balanced mode and click Next.
Enter the amount of sWETH_t tokens and perform the swap to WETH.
Go to the Liquidity tab in the Yield section on the xeoTaiko pool page: https://app.crosscurve.fi/liquidity?pool=0xe16ab7fb5d2c7c1b69f7ce58d390b78ab59e44ae&type=curve&action=deposit&input=0x346704605c72d9f5f9f02d651e5a3dcce6964f3d&output=0xa494f19b34f6aa77ce6d968c752b6321d7b069b3&chainIn=146&chainOut=167000 Select the Deposit action in Balanced mode and click Next.
Enter the amount of xfrxETH tokens and perform the swap to sxfrxETH_s.
sxfrxUSD_s tokens on the Taiko network can be obtained by exchanging them for assets available in the xsoTaiko pool in the CrossCurve application.
1. Go to the Liquidity tab in the Yield section. Select the Deposit action in Balanced mode, then click Next.
Choose the desired asset and enter the amount you want to exchange, then confirm the spend by clicking Approve, and sign the transaction in your wallet.
Click Swap to exchange and confirm the transaction in your wallet.
2. If you know the exchange direction, you can perform the swap in the Trade tab for any available asset using the Advanced mode .
Note: in some directions, high slippage may occur!
sxfrxETH_s tokens on the Taiko network can be swapped into from any available asset in the xeoTaiko pool in the CrossCurve application.
1. Go to the Liquidity tab in the Yield section. Select the Deposit action in Balanced mode, then click Next.
Choose the desired asset and enter the amount you want to exchange, then confirm the spend by clicking Approve, and sign the transaction in your wallet.
Click Swap to exchange and confirm the transaction in your wallet.
1. If you know the exchange direction, you can perform the swap in the Trade tab for any available asset using the Advanced mode .
Attention: in some directions, high slippage may occur!
Go to the CrossCurve Stable pool page https://www.curve.finance/dex/taiko/pools/factory-stable-ng-5/deposit/ and connect your wallet.
Enter the desired deposit amount in the Deposit tab. To avoid losses due to slippage, it is recommended to deposit funds using the balanced method by clicking Add all coins in a balanced proportion (more details here).
With the first transaction, confirm the spend by clicking Approve Spending and signing the transaction in your wallet.
With the second transaction, deposit the funds by clicking Deposit and signing the transaction in your wallet.
After successfully confirming the transaction on-chain, the amount of received xsoTaiko LP tokens will be reflected in your wallet and in the Your Details tab.
If your wallet does not support automatic token addition, add it manually as a custom token using the contract address 0xA17aa5eE656849221C8d9d062894e1145CbdA864 on the Taiko network.
Upgradeable (UUPS Pattern): The contract can be updated while preserving state.
Owner-Based Access Control: Critical functions (like upgrading the contract and updating campaign parameters) are restricted to the owner.
Reward Notification: The notifyRewardAmount function can only be invoked by the authorized escrow vote manager, ensuring a controlled flow of rewards.
Campaign Parameters: The gauge uses dynamic campaign parameters (s_campaignParameters) to manage reward distribution schedules and amounts, which can be updated by the owner if needed.
By implementing IGaugeV1, GaugeV1 provides a standardized interface for initializing, updating campaign parameters, and receiving new reward amounts within the CrossCurve ecosystem.
UUPSUpgradeable (OpenZeppelin): Enables upgradeability under the UUPS (Universal Upgradeable Proxy Standard) pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Provides ownership logic, limiting certain state changes (e.g., upgrading, updating parameters) to the contract owner.
IGaugeV1:
Interface defining core functions (e.g., initialize, updateCampaignParameters, notifyRewardAmount) and events (RewardNotified, CampaignParametersUpdated) for the gauge contract.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Library and interface for safe ERC20 token transfers.
IEscrowVoteManagerV1:
Tracks and authorizes reward notifications, ensuring that only the designated manager can call notifyRewardAmount.
IDistributionCreator: Contract on Arbitrum that actually creates or schedules distribution campaigns (Merkl distributions).
The contract uses DISTRIBUTION_CREATOR with a known address (0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd) on Arbitrum.
EPOCH_DURATION: The duration of an epoch (1 week). Used to align reward distribution campaigns with discrete time intervals.
DISTRIBUTION_CREATOR: The address of the Merkl distribution contract on Arbitrum. This contract is responsible for orchestrating reward distributions once campaigns are created.
s_escrowVoteManager (address)
Address of the escrow vote manager contract, which is authorized to call notifyRewardAmount.
s_eywa (address)
The EYWA token address used for rewards distribution.
s_campaignParameters (IDistributionCreator.CampaignParameters)
Holds the current campaign parameters for distributing rewards. These parameters include data like amount, duration, start timestamp, and distribution logic, which can be updated by the owner.
Description:
Disables contract initializers to prevent multiple initializations. Enforces that initialize can be called only once in a UUPS upgradeable context.
Description:
Initializes the gauge contract by setting the owner, escrow vote manager, EYWA token address, and the initial campaign parameters for rewards.
Can only be called once, marked by the initializer modifier from OpenZeppelin upgradeable patterns.
Parameters:
owner_: The address designated as the contract owner.
escrowVoteManager_: The address of the escrow vote manager, authorized to call notifyRewardAmount.
eywa_: The address of the EYWA token used for distributing rewards.
Effects:
Calls __UUPSUpgradeable_init() and __Ownable_init(owner_) to set up UUPS upgrade and ownership.
Assigns s_escrowVoteManager and s_eywa references.
Description:
Allows the contract owner to update the gauge’s campaign parameters.
The newly provided parameters (newCampaignParameters_) overwrite the existing ones in s_campaignParameters.
Parameters:
newCampaignParameters_: The updated distribution parameters (e.g., new schedule or amounts) for this gauge.
Events:
Emits CampaignParametersUpdated(address(this), oldCampaignParameters, newCampaignParameters_) to log the changes.
Description:
Notifies the gauge of a newly available amount_ of EYWA tokens to be distributed as rewards.
Can only be called by s_escrowVoteManager.
The function transfers amount_ from the caller to this gauge, checks if the resulting balance is sufficient to meet the minimum distribution threshold, and if so, triggers the distribution campaign via DISTRIBUTION_CREATOR.createCampaign(...).
Parameters:
amount_: The amount of EYWA tokens to be added for distribution.
Checks & Logic:
Verifies msg.sender == s_escrowVoteManager, otherwise reverts with UnauthorizedCaller().
Transfers amount_ of EYWA from the caller to the contract.
Events:
RewardNotified(amount_) logs the newly notified reward amount.
Description:
Ensures that only the contract owner can authorize upgrades.
Enforced by the UUPSUpgradeable pattern.
RewardNotified(uint256 indexed amount)
Emitted when new rewards are notified to the gauge, indicating the total tokens added.
CampaignParametersUpdated( address indexed gauge, IDistributionCreator.CampaignParameters oldCampaignParameters, IDistributionCreator.CampaignParameters newCampaignParameters )
Logged when the owner updates the gauge’s distribution campaign parameters.
UnauthorizedCaller()
Thrown if a function restricted to s_escrowVoteManager or onlyOwner is called by an unauthorized address.
GaugeV1 is an upgradeable contract that manages reward distributions for a specific pool or strategy within the CrossCurve ecosystem. By connecting to an Escrow Vote Manager, it ensures only authorized parties can add new rewards (notifyRewardAmount). Through DistributionCreator on Arbitrum, it transforms these rewards into time-bound distribution campaigns. The contract owner can update campaign parameters if needed, while all major functionalities (initialization, upgrade, parameter updates) remain protected by ownership and authorized checks.
CrossCurve Consensus Bridge (CCB) is a cross-chain communication protocol that enables reliable data and asset transfers between networks without relying on centralized intermediaries.
The system is built on a consensus mechanism among independent cross-chain messaging services, ensuring the authenticity of cross-chain messages received on the destination network.
The goal of CCB is to provide developers with a secure way to connect their dApps, DeFi protocols, DAOs, and Infrastructure Services to a multi-network ecosystem using a standardized API and a minimal set of dependencies.
The fundamental model of cross-chain interaction has been used in various forms for quite some time.
In blockchain A, a contract calls a bridge contract function to send data to blockchain B. The bridge contract emits an event, which is picked up by its off-chain service. This service then creates a transaction containing the necessary data for the corresponding bridge contract on blockchain B. Upon receiving the transaction, the bridge contract verifies its validity and then invokes the target contract function, passing along the data received from blockchain A.
One of the core challenges lies in the fact that the bridge service operates outside the blockchain environment and therefore cannot be verified on-chain. Different bridge protocols address this issue in different ways.
CrossCurve Consensus Bridge, however, introduces a more comprehensive approach. It is not meant to replace existing protocols - instead, it integrates and leverages their mechanisms, creating a unified and verifiable cross-chain communication layer.
The sender initiates a message in the source network by calling the CrossCurve Gatekeeper contract.
Depending on the destination chain, the Gatekeeper prepares and executes parallel message dispatches through multiple supported protocols. One of these protocols transmits the full message payload, while the others send verification proofs to confirm message authenticity.
Each protocol, following its standard cross-chain messaging process, independently delivers its data to the CrossCurve Receiver contract in the destination network.
CrossCurve Consensus Bridge provides a truly secure mechanism for cross-chain messaging.
Its minimal configuration requires three sovereign cross-chain protocols.
Even in this base setup, an attacker would need to gain simultaneous control over at least two out of the three protocols to compromise a message — making unauthorized interference practically infeasible.
Decentralization is one of the most effective defenses against censorship.
However, in many cross-chain systems, services are often built on specific infrastructure stacks, which introduces potential points of control and censorship.
CrossCurve Consensus Bridge eliminates this issue by leveraging sovereign protocols that operate independently from one another.
For an adversary to block or alter message delivery through the bridge, they would need to control more than 50% of the protocols participating in the message channel (in the minimal setup, that means controlling two out of three).
The consensus of independent protocols ensures not only security but also fault tolerance in message transmission. Even in its minimal configuration, if one of the three protocols becomes temporarily unavailable, the remaining two are sufficient to keep the CrossCurve Consensus Bridge fully operational.
In the rare event of a deadlock — when one or more bridges within the consensus experience prolonged downtime, potentially locking assets that relied on the consensus bridge — the situation remains recoverable. The can replace the affected protocols in the consensus bridge of the impacted chain by approving a dedicated governance proposal.
The CrossCurve Consensus Bridge is engineered for maximum security through the use of consensus among independent bridge protocols for data transmission.
Yet even the most secure systems can face potential vulnerabilities. The most common vector of attack targets governance mechanisms — an adversary might attempt to alter the composition of participating bridges, making it easier to compromise a single one.
In CrossCurve Consensus Bridge, such a scenario is structurally impossible.
Bridge configuration across all chain pairs is managed exclusively by the CrossCurve DAO. Any modification requires explicit community approval. The voting process lasts 7 days, and even after a proposal passes, the new configuration takes effect only after 24 hours, providing an additional safeguard and ensuring transparent governance.
This underlines the critical role of the CrossCurve DAO in maintaining decentralization across cross-chain messaging.
We believe that greater decentralization and resilience can be achieved when ecosystem participants — those advocating for transparency, stability, and security — become active members of the CrossCurve DAO. Their participation strengthens governance integrity and makes malicious decisions significantly harder to pass.
This is the foundation for building advanced cross-chain applications.
Through the Consensus Bridge, dApps gain a reliable communication layer between their instances deployed across different blockchains - or with APIs of other applications operating in separate networks.
Cross-chain token transfer applications using any combination of lock/mint or burn/mint models can rely on the Consensus Bridge as a trustless verification layer.
It provides accurate and verifiable information about token locking, minting, unlocking, or burning events across different blockchains.
The Consensus Bridge integrates seamlessly into the LayerZero cross-chain verification system.
This is achieved through a wrapper module called SuperDVN, which externally behaves like a standard DVN but internally performs multi-protocol consensus verification for enhanced security and reliability.
Currently, the CrossCurve Consensus Bridge supports the following messaging protocols:
CrossCurve Oracle Network
The integration with the Consensus Bridge is planned to be permissionless. However, the protocol is currently operating in an experimental mode. If you’d like to connect, please contact us
To send a message to a recipient on another chain, you need to:
Prepare the calldata for the target contract function with the required parameters.
Call the sendData function on the CrossCurve Gatekeeper contract:
To configure the bridge, use the following contract addresses.
For proper operation, the contracts must be deployed on both the source and destination blockchains.
uint256 public constant EPOCH_DURATION = 1 weeks;
IDistributionCreator public constant DISTRIBUTION_CREATOR = IDistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);constructor() {
_disableInitializers();
}function initialize(
address owner_,
address escrowVoteManager_,
address eywa_,
IDistributionCreator.CampaignParameters calldata campaignParameters_
)
external
initializerfunction updateCampaignParameters(
IDistributionCreator.CampaignParameters calldata newCampaignParameters_
)
external
onlyOwnerfunction notifyRewardAmount(uint256 amount_) externalfunction _authorizeUpgrade(address) internal override onlyOwnercampaignParameters_: Initial set of campaign parameters (amount, duration, schedule, etc.) used in distribution campaigns.
Stores s_campaignParameters from input.
If the new balance (multiplied by 1 hour / EPOCH_DURATION) meets the rewardTokenMinAmounts(...) requirement of DISTRIBUTION_CREATOR, the contract approves DISTRIBUTION_CREATOR to spend its entire balance and initiates a campaign:
Sets m_campaignParameters.amount to the new gauge balance.
Sets startTimestamp = uint32(block.timestamp).
Sets duration = uint32(EPOCH_DURATION) (one week).
Calls createCampaign(...) on DISTRIBUTION_CREATOR.
Emits RewardNotified(amount_).




























































































































The external service CrossCurve Pusher monitors these events. Once the original message and a sufficient number of verification confirmations are detected, it submits an execution transaction to the CrossCurve Receiver contract.
Upon receiving the transaction from CrossCurve Pusher, the Receiver verifies the existence of the original message and all required confirmations from other protocols.
If validation is successful, the verified message is then delivered to its designated recipient.
Ethereum Sepolia Testnet
Arbitrum Sepolia Testnet
BNB Smart Chain (BSC) Testnet
Sonic Testnet



EmissionManagerV1 is an upgradeable contract that orchestrates weekly EYWA token emissions to various distribution streams, such as rebase rewards, gauge rewards, bonds, grants, and incentives. It integrates with the Escrow Manager to evaluate locked token balances and applies distinct emission formulas depending on whether the total locked tokens exceed a specified threshold. The contract also enforces constraints on weekly emissions, such as cooldown periods, maximum percentage increases, and valid distribution percentages.
Key Features:
Epoch-Based Emissions: Emissions occur in discrete one-week epochs, with a configurable weekly emission amount.
Distribution Percentages: Tokens are split among rebase rewards, bonds, grants, and incentives, each receiving a percentage of the weekly emission.
Threshold-Based Adjustments: If total locked tokens exceed a s_lockThreshold, alternate base rates and multipliers are applied to rebase calculations.
By implementing the IEmissionManagerV1 interface, EmissionManagerV1 provides a clear set of functionalities and events essential for managing the emission process in the CrossCurve ecosystem.
UUPSUpgradeable (OpenZeppelin): Enables the contract to be upgradeable via a UUPS proxy pattern, ensuring only the owner can perform upgrades.
OwnableUpgradeable (OpenZeppelin): Provides ownership functionality, restricting sensitive actions (like parameter updates) to the owner.
IEmissionManagerV1:
Interface declaring all essential methods (e.g., initialize, updateEpoch) and events for managing emissions.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Used for secure ERC20 operations.
IEscrowVoteManagerV1: Receives gauge emission amounts and coordinates gauge reward distribution.
IEscrowManager: Provides total locked token data for rebase emission calculations.
ITreasury: Manages treasury funds from which weekly emissions are withdrawn.
EPOCH_DURATION: Duration of each emission epoch (1 week).
TOTAL_SUPPLY: Total EYWA token supply (1 billion).
MAXIMUM_EMISSION_INCREASE_PERCENTAGE: Maximum allowed percentage by which the weekly emission can increase, scaled by PRECISION.
s_currentWeeklyEmission (uint256): Current weekly emission amount in EYWA tokens.
s_totalDistributedEmission (uint256): Accumulated amount of EYWA tokens distributed across all epochs.
s_gaugeEmissionPercentage (uint256): Percent of weekly emission allocated to gauge rewards, scaled by PRECISION.
s_bondEmissionPercentage (uint256): Percent allocated to bond rewards, scaled by PRECISION.
s_grantEmissionPercentage (uint256)
s_lockThreshold (uint256): The threshold of total locked tokens determining which emission formula to apply.
s_baseRateBelowThreshold (uint256): Base rate for rebase emission if locked tokens < s_lockThreshold.
s_baseRateAboveThreshold (uint256): Base rate if locked tokens ≥ s_lockThreshold
s_initialInflationRate (uint256): Inflation rate applied when locked tokens are below threshold.
s_secondaryInflationRate (uint256): Inflation rate used when locked tokens are above threshold.
s_currentEpochStart (uint256): Timestamp marking the start of the current emission epoch.
s_lastChangeEpochStart (uint256): Timestamp marking the start of the epoch during the last emission state change (used for cooldown enforcement).
s_epochCounter (uint256): Number of completed epochs.
s_treasury (address): Address holding the EYWA tokens (treasury).
s_rebaseRewardsDistributor (address): Distributor for rebase rewards.
s_bondEmissionDistributor (address): Distributor for bond emissions.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
initialize(...)Description: Initializes the contract for the first time, setting the owner, treasury, emission distributors, and references to external managers/tokens. Configures initial weekly emission, distribution percentages, threshold-based rates, and inflation rates.
Parameters:
owner_: Contract owner address.
treasury_: Address of treasury holding EYWA tokens.
rebaseRewardsDistributor_: Distributor contract for rebase rewards.
Effects:
Calls __UUPSUpgradeable_init() and __Ownable_init(owner_).
Sets initial values for emission rates, thresholds, and inflation parameters.
Marks the start of the current epoch.
updateTreasury(address newTreasury_)Description: Updates the treasury address from which emissions are withdrawn.
Events:
Emits TreasuryUpdated(newTreasury_).
updateEmissionDistributors(...)Description: Updates the addresses for bond, grant, and incentive emission distributors. Only callable by the owner.
Parameters:
newBondEmissionDistributor_: New bond emission distributor address.
newGrantEmissionDistributor_: New grant emission distributor address.
newIncentiveEmissionDistributor_: New incentive emission distributor address.
Events:
Emits EmissionDistributorsUpdated.
updateWeeklyEmissionState(...)Description:
Adjusts the weekly emission amount and distribution percentages. Enforces a cooldown (EPOCH_COOLDOWN_PERIOD) since the last change and forbids increases above the allowed percentage limit.
Checks & Constraints:
Must have at least 1 epoch (s_epochCounter > 0).
Enforces cooldown: block.timestamp must be ≥ s_lastChangeEpochStart + EPOCH_COOLDOWN_PERIOD * EPOCH_DURATION.
newWeeklyEmission_ must not exceed historical average times MAXIMUM_EMISSION_INCREASE_PERCENTAGE / PRECISION
Events:
Emits WeeklyEmissionStateUpdated.
updateParameters(...)Description: Updates threshold-based emission parameters, including base rates, rate multipliers, and inflation rates used in rebase calculations.
Events:
Emits ParametersUpdated with the updated values.
updateEpoch()Description:
If a new epoch has started (block.timestamp >= s_currentEpochStart + EPOCH_DURATION), the contract calculates distributions for the new week and transfers tokens to the various distributors.
Logic:
Withdraws s_currentWeeklyEmission from s_treasury.
Calculates rebase emission portion with _calculateRebaseEmission.
Sends rebase emission to the rebase rewards distributor and calls checkpoint().
Events:
Emits EpochUpdated with detailed breakdown.
averageWeeklyEmissionOverTime()Description:
Returns the average weekly emission across all completed epochs:
s_totalDistributedEmission / s_epochCounter.
_authorizeUpgrade(address)Description: Restricts the UUPS upgrade function to the contract owner.
_calculateRebaseEmission(uint256 currentWeeklyEmission_)Description:
Derives the rebase portion of the weekly emission based on total locked tokens from s_escrowManager.
If m_totalLocked >= s_lockThreshold, uses one set of base rates, multipliers, and s_secondaryInflationRate.
Otherwise, uses another set and s_initialInflationRate.
Return:
rebaseEmission_: The final rebase token amount.
Formula Components:
Computes an adjustment factor that depends on s_baseRateAboveThreshold/s_rateMultiplierAboveThreshold or s_baseRateBelowThreshold/s_rateMultiplierBelowThreshold.
Adds an inflation portion scaled by either s_secondaryInflationRate or s_initialInflationRate.
TreasuryUpdated(address newTreasury)
EmissionDistributorsUpdated(address newBondEmissionDistributor, address newGrantEmissionDistributor, address newIncentiveEmissionDistributor)
WeeklyEmissionStateUpdated(uint256 newWeeklyEmission, uint256 newGaugeEmissionPercentage, ..., uint256 newIncentiveEmissionPercentage)
These events log critical changes such as treasury updates, changes to emission distribution, parameter updates, and epoch transitions.
InvalidCallee(): Thrown if an unauthorized entity calls certain functions (not used in current logic).
ZeroEpochCounter(): Thrown if updateWeeklyEmissionState is called before any epoch has elapsed.
CooldownPeriodNotElapsed(): Thrown if a new weekly emission state update is attempted within the cooldown period.
EmissionManagerV1 is a flexible and upgradeable contract for distributing EYWA tokens weekly to different reward mechanisms—governed by configurable rates and distribution percentages. By leveraging a threshold-based logic, it dynamically adjusts rebase emissions based on the total locked tokens, ensuring that ecosystem participation and inflation rates are balanced. It integrates seamlessly with treasury, escrow, and reward distributor contracts to enforce cooldowns, respect maximum emission growth, and emit relevant events detailing emission updates.
RebaseRewardsDistributorV1 is an upgradeable contract that distributes rebase rewards to veEYWA token holders (locks) in the CrossCurve ecosystem. It relies on an Emission Manager (s_emissionManager) to trigger epoch updates (checkpoints) and fetches locked token data from an Escrow Manager (s_escrowManager). The contract tracks weekly reward distributions and lets veEYWA token holders claim these rebase rewards either directly (if their lock is expired) or by depositing rewards back into the lock (if it’s still active).
Key features include:
Epoch-Based Distribution: Rewards are recorded in discrete weekly intervals (epochs) and credited to locks according to each lock’s proportional voting power during the relevant weeks.
Checkpointing Logic: Every time new rebase rewards are added, the contract updates an internal “checkpoint,” distributing the newly added tokens proportionally over the elapsed time since the last checkpoint.
On-Chain Rebase: Locks continuously earn rebase rewards over time; once claimed, if the lock is still active (not past unlockTime), the rewards are automatically re-deposited. Otherwise, they are transferred to the lock owner.
By implementing IRebaseRewardsDistributorV1, RebaseRewardsDistributorV1 ensures a standardized interface for initialization, checkpoint updates, and reward claims within the CrossCurve ecosystem.
UUPSUpgradeable (OpenZeppelin): Provides functionality for upgradeable contracts following the UUPS (Universal Upgradeable Proxy Standard) pattern.
OwnableUpgradeable (OpenZeppelin): Gives ownership control, allowing only the owner to authorize upgrades and perform restricted actions.
IRebaseRewardsDistributorV1 (Custom Interface):
Declares the core functions (e.g., initialize, checkpoint, claim) and events (
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): For safe ERC20 transfers of the EYWA token.
IEscrowManager: Provides locked token data (voting power snapshots, unlockTime, ownership).
IEmissionManagerV1: Signals new epochs by calling checkpoint() and ensures emission periods are up-to-date.
EPOCH_DURATION: Specifies that each distribution epoch is exactly one week (604,800 seconds).
s_rewardsStartTime (uint256)
The timestamp (rounded down to the nearest week) at which rewards distribution officially begins.
s_lastCheckpointTime (uint256)
Description:
Disables initializers for this upgradeable contract, ensuring initialize is called only once in a UUPS proxy context.
initialize(...)Description:
Sets up initial state for the rebase rewards distributor:
Assigns contract ownership to owner_.
checkpoint()Description:
Called only by s_emissionManager to record a new checkpoint, distributing newly added tokens across the weeks since the last checkpoint.
Reverts if msg.sender != s_emissionManager with UnauthorizedCaller().
claim(uint256 tokenId_)Description:
Lets a user claim the rebase rewards for a single veEYWA lock identified by tokenId_.
Requires that s_emissionManager.s_currentEpochStart() be updated to or beyond the current week; otherwise reverts with EmissionPeriodNotUpdated().
claim(uint256[] calldata tokenIds_)Description:
Claims rewards for multiple lock IDs in a single transaction.
Similar checks to claim(uint256), verifying the emission period is updated.
Iterates over each
earned(uint256 tokenId_)Description:
Returns how many tokens the lock with tokenId_ has accumulated but not yet claimed, using the latest known checkpoint.
Internally calls _earned(...) with s_lastCheckpointTime / EPOCH_DURATION * EPOCH_DURATION as the last checkpoint boundary.
_checkpoint()Description:
The core logic that distributes newly added EYWA tokens among each weekly interval from the last checkpoint time until block.timestamp.
If a portion of a week is included, it distributes a proportional share.
_claim(...)Description:
Internal function that calculates how many rebase rewards tokenId_ has earned since its last claim, updates the last claimed time, and emits RewardsClaimed.
Returns the amount of newly claimed rewards.
_earned(...)Description:
Calculates how many tokens the lock tokenId_ earned from m_initialWeekCursor to lastCheckpointTime_, iterating in weekly increments.
Uses historical voting power from the escrowManager.getPastVotesByTokenId(...)
Checkpoint(uint256 indexed timestamp, uint256 indexed totalReward)
Emitted whenever _checkpoint() distributes a new batch of tokens across weekly intervals.
timestamp: The timestamp of the checkpoint (usually block.timestamp).
UnauthorizedCaller()
Thrown if checkpoint() is called by an entity other than s_emissionManager.
EmissionPeriodNotUpdated()
No additional custom errors are introduced beyond those declared in the IRebaseRewardsDistributorV1 interface.
RebaseRewardsDistributorV1 provides a specialized, upgradeable system for distributing weekly rebase rewards to locks in the CrossCurve ecosystem. It does so by:
Recording new tokens from the emission manager in discrete weekly intervals via _checkpoint().
Allowing token holders to claim their proportional share of rebase rewards at any time, either receiving them directly if their lock is expired or re-depositing them if their lock remains active.
Integrating with the escrow manager to read historical voting power for each epoch and proportionally allocate weekly distributed tokens.
By bridging data from the emission manager and the escrow manager, RebaseRewardsDistributorV1 ensures consistent rebase reward accounting that reflects each lock’s relative stake and time-based accumulation of benefits. It complements the rest of the CrossCurve ecosystem by providing a secure, time-based rebase distribution mechanism with minimal overhead and clear upgrade paths.
sendData(
bytes calldata data,
bytes32 to,
uint64 chainIdTo,
bytes[] memory currentOptions
) external nonReentrant returns(uint256 fee)2. Checking the code in accordance with the vulnerabilities checklist:
Eliminate typical vulnerabilities (e.g. reentrancy, gas limit, flash loan attacks etc.).
3. Checking the code for compliance with the desired security model:
Detect inconsistencies with the desired model.
4. Consolidation of the auditors' interim reports into one:
Double-check all the found issues to make sure they are relevant and the determined threat level is correct.
Provide the Client with an interim report.
5. Bug fixing & re-audit:
Verify the fixed code version with all the recommendations and its statuses.
Provide the Client with a re-audited report.
6. Final code verification and issuance of a public audit report:
Conduct the final check of the code deployed on the mainnet.
Provide the Customer with a public audit report.
A group of auditors are involved in the work on the audit. Security engineers check the provided source code independently of each other in accordance with the methodology described below:
1. Project architecture review:
Build an independent view of the project's architecture.
Identifying logical flaws.
2. Checking the code in accordance with the vulnerabilities checklist: Eliminate typical vulnerabilities (e.g. reentrancy, gas limit, flash loan attacks etc.).
3. Checking the code for compliance with the desired security model:
Detect inconsistencies with the desired model.
4. Consolidation of the auditors' interim reports into one:
Double-check all the found issues to make sure they are relevant and the determined threat level is correct.
Provide the Client with an interim report.
5. Bug fixing & re-audit:
Verify the fixed code version with all the recommendations and its statuses.
Provide the Client with a re-audited report.
6. Final code verification and issuance of a public audit report:
Conduct the final check of the code deployed on the mainnet.
Provide the Customer with a public audit report.
🔗 Link to MixBytes EYWA reports.
The core architectural element of the CrossCurve ecosystem is the CrossCurve Cross-chain Data Protocol, which is a transport layer between blockchains. All CrossCurve products for DeFi users are based on this protocol.
Although at the time of this audit the core of CrossCurve multisig is represented by a trusted group of projects, CrossCurve aims for DAO, as reflected in CrossCurve project current documentation.
CDP Smart Contracts: These smart contracts serve as a means for sending and accepting cross-chain calls. They also include a node registration contract used in the Proof of Authority (POA) consensus among oracle nodes.
Smart State evaluation: 8/10
5MB05062305_EYWA_CDP_SС_report.pdfpdfCDP report from SmartState
CrossCurve Cross-chain Liquidity Protocol ensures the operation of EYWA DEX v1
CLP smart contracts - are smart contracts for processing synth and burn operations, as well as mint and lock tokens. They are also responsible for swap processing and liquidity handling operations.
Smart State evaluation: 10/10
🔗 Link to SmartState CrossCurve reports.
The Hexens team audited various components of CrossCurve, such as the BLS cryptography module in CrossCurve CDP as well as EYWA NFT.
s_initialInflationRate and s_secondaryInflationRate) further influence the rebase portion of weekly emissions.Owner-Only Updates: Certain parameters, such as weekly emission amounts and distribution logic, can only be updated by the contract owner, subject to cooldowns and other constraints.
IRebaseRewardsDistributorV1: Distributes rebase rewards and triggers relevant accounting updates.
EPOCH_COOLDOWN_PERIOD: Number of epochs required between emission state changes.
PRECISIONs_incentiveEmissionPercentage (uint256): Percent allocated to incentives, scaled by PRECISION.
s_rateMultiplierBelowThreshold (uint256): Rate multiplier if locked tokens < s_lockThreshold.
s_rateMultiplierAboveThreshold (uint256): Rate multiplier if locked tokens ≥ s_lockThreshold.
s_grantEmissionDistributor (address): Distributor for grant emissions.s_incentiveEmissionDistributor (address): Distributor for incentive emissions.
s_escrowVoteManager (IEscrowVoteManagerV1): Escrow vote manager contract for gauge emissions.
s_escrowManager (IEscrowManager): Escrow manager providing locked token data.
s_eywa (IERC20): EYWA token used for emission distributions.
bondEmissionDistributor_: Distributor contract for bond rewards.grantEmissionDistributor_: Distributor contract for grants.
incentiveEmissionDistributor_: Distributor contract for incentives.
escrowVoteManager_: The escrow vote manager contract instance.
escrowManager_: Escrow manager contract instance for locked token data.
eywa_: EYWA token contract.
Sum of new distribution percentages = PRECISION (100%).
Distributes leftover among gauge, bond, grant, and incentive streams proportionally.
Increments s_epochCounter and updates s_totalDistributedEmission.
Divides by 1e18 at the end to restore integer arithmetic precision.
ParametersUpdated(..., uint256 initialInflationRate, uint256 secondaryInflationRate)
EpochUpdated(uint256 epochStartTimestamp, uint256 totalEmission, uint256 rebaseEmission, ..., uint256 incentiveEmission)
ExcessiveEmissionIncrease(): Thrown if the new weekly emission exceeds the allowed maximum over historical average.
InvalidPercentagesSum(): Thrown if the sum of new distribution percentages does not equal PRECISION (100%).
uint256 public constant EPOCH_DURATION = 1 weeks;
uint256 public constant TOTAL_SUPPLY = _000_000_000e18;
uint256 public constant MAXIMUM_EMISSION_INCREASE_PERCENTAGE = 25_000;
uint256 public constant PRECISION = 00_000;
uint256 public constant EPOCH_COOLDOWN_PERIOD = 12;constructor() {
_disableInitializers();
}function initialize(
address owner_,
address treasury_,
address rebaseRewardsDistributor_,
address bondEmissionDistributor_,
address grantEmissionDistributor_,
address incentiveEmissionDistributor_,
IEscrowVoteManagerV1 escrowVoteManager_,
IEscrowManager escrowManager_,
IERC20 eywa_
) external initializerfunction updateTreasury(address newTreasury_) external onlyOwnerfunction updateEmissionDistributors(
address newBondEmissionDistributor_,
address newGrantEmissionDistributor_,
address newIncentiveEmissionDistributor_
) external onlyOwnerfunction updateWeeklyEmissionState(
uint256 newWeeklyEmission_,
uint256 newGaugeEmissionPercentage_,
uint256 newBondEmissionPercentage_,
uint256 newGrantEmissionPercentage_,
uint256 newIncentiveEmissionPercentage_
) external onlyOwnerfunction updateParameters(
uint256 lockThreshold_,
uint256 baseRateBelowThreshold_,
uint256 rateMultiplierBelowThreshold_,
uint256 baseRateAboveThreshold_,
uint256 rateMultiplierAboveThreshold_,
uint256 initialInflationRate_,
uint256 secondaryInflationRate_
) external onlyOwnerfunction updateEpoch() externalfunction averageWeeklyEmissionOverTime() external view returns (uint256)function _authorizeUpgrade(address) internal override onlyOwnerfunction _calculateRebaseEmission(uint256 currentWeeklyEmission_) private view returns (uint256)Owner-Only Upgrades: Using a UUPS proxy pattern, only the contract owner can authorize upgrades to the distributor’s logic.
CheckpointRewardsClaimedTimestamp of the most recent checkpoint, marking when the contract last distributed tokens among the weekly intervals.
s_previousTokenBalance (uint256)
The EYWA token balance in the contract before the most recent checkpoint. Used to calculate how many new tokens were added since the last checkpoint.
s_eywa (IERC20)
The EYWA token contract used for rebase rewards.
s_escrowManager (IEscrowManager)
The escrow manager contract that manages veEYWA locks and provides historical voting power data.
s_emissionManager (IEmissionManagerV1)
The emission manager contract that calls checkpoint() each time new rebase rewards are determined.
s_weeklyTokensDistributed (uint256[1000000000000000])
A large array mapping from a week’s starting timestamp (multiple of EPOCH_DURATION) to the total tokens distributed in that particular week.
s_lastClaimedTimeByTokenId (mapping(uint256 => uint256))
For each veEYWA token ID, stores the last epoch’s timestamp at which it fully claimed rebase rewards.
escrowManager_ to pull unlimited EYWA tokens from this contract.Records the start time of rewards (s_rewardsStartTime = current week boundary) and sets initial s_lastCheckpointTime similarly.
Links the references to s_eywa, s_escrowManager, and s_emissionManager.
Parameters:
owner_: The address designated as the contract owner.
eywa_: The EYWA token contract used for distributing rebase rewards.
escrowManager_: The contract that manages locked positions (NFT-based locks).
emissionManager_: The contract that triggers checkpoint updates.
Logic:
Checks authorization.
Calls _checkpoint() to distribute any new tokens proportionally among the weeks that have elapsed since s_lastCheckpointTime.
Logic:
Checks if the emission manager’s s_currentEpochStart() is updated to the current epoch.
Calls _claim(tokenId_, lastCheckpointWeekBoundary).
If the lock is expired (block.timestamp >= unlockTime), transfers the earned reward to the last lock owner. Otherwise, it deposits the reward back into the lock via escrowManager_.depositFor(...).
Deducts the claimed reward from s_previousTokenBalance.
tokenId_tokenIds__claim(...)Return:
uint256: The unclaimed rebase reward balance for that particular lock ID.
Calculates m_totalReward = currentBalanceOfContract - s_previousTokenBalance.
Spreads this m_totalReward proportionally across all full or partial weeks from s_lastCheckpointTime to block.timestamp.
For each week boundary, updates s_weeklyTokensDistributed[weekTimestamp] += the portion of tokens corresponding to that interval.
Updates s_previousTokenBalance to the current contract balance.
Sets s_lastCheckpointTime = block.timestamp.
Emits Checkpoint(block.timestamp, m_totalReward).
Logic:
Calls _earned(tokenId_, lastCheckpointTime_) to compute (m_reward, m_initialWeekCursor, m_updatedWeekCursor).
Sets s_lastClaimedTimeByTokenId[tokenId_] = m_updatedWeekCursor.
If m_reward == 0, returns immediately. Otherwise emits RewardsClaimed(tokenId_, m_initialWeekCursor, m_updatedWeekCursor, m_reward).
Returns m_reward to the caller for final deposit/transfer logic.
escrowManager.getPastTotalSupply(...)s_weeklyTokensDistributedLogic:
Retrieves m_initialWeekCursor = s_lastClaimedTimeByTokenId[tokenId_]. If zero, attempts to set it from the lock’s first recorded epoch data in s_votingPowerPointByTokenIdAndEpoch.
If m_initialWeekCursor >= lastCheckpointTime_, returns zero reward (nothing new to claim).
Iterates at most 52 times (1 year lookback in weekly steps):
For each weekly boundary from m_updatedWeekCursor to lastCheckpointTime_, calculates:
m_balance = escrowManager.getPastVotesByTokenId(tokenId_, nextWeekTimestamp)
Returns (m_reward, m_initialWeekCursor, m_updatedWeekCursor).
totalReward: The number of newly added tokens distributed.
RewardsClaimed(uint256 indexed tokenId, uint256 indexed initialWeekCursor, uint256 indexed updatedWeekCursor, uint256 reward)
Emitted whenever a token ID claims rebase rewards.
tokenId: The veEYWA NFT lock ID that claimed.
initialWeekCursor: The earliest week boundary for which new rewards are being claimed.
updatedWeekCursor: The new last claimed week boundary.
reward: The total tokens claimed in this operation.
Thrown if a user attempts to claim but the emission manager’s s_currentEpochStart() has not been advanced to the current week boundary.
IncentiveRewardsDistributor is a contract that builds upon an abstract RewardsDistributor to manage the distribution of incentive rewards within the CrossCurve ecosystem. The RewardsDistributor base contract provides fundamental logic for tracking deposits, withdrawals, reward notifications, and reward claims over discrete epochs. The IncentiveRewardsDistributor adds:
Whitelisting of Tokens: Before accepting a new token as a reward token, it checks with the escrow vote manager to ensure it is whitelisted.
Escrow Vote Manager Authorization: Restricts calls to certain functions (like getReward) to only the authorized vote manager.
Inheritance and Extended Logic: Integrates seamlessly with the epoch-based deposit/withdraw system in RewardsDistributor to finalize reward amounts and calculations.
By implementing IIncentiveRewardsDistributor, this contract conforms to a standard reward distributor interface used throughout the CrossCurve ecosystem.
RewardsDistributor (Abstract Contract):
Manages core reward distribution functionality, such as:
Tracking how many tokens each owner has deposited during a specific epoch.
Storing how many rewards are allocated to a token for each epoch.
Additional External References:
IEscrowVoteManagerV1:
Provides s_isWhitelistedToken to validate new reward tokens.
Acts as an authorization gate for methods that require msg.sender to be the vote manager.
The base RewardsDistributor constructor sets immutable references for ESCROW_VOTE_MANAGER and ESCROW_MANAGER. It also defines the following main categories of functionality:
Epoch-Based Deposit and Withdrawal:
deposit(uint256 amount_, uint256 tokenId_)
withdraw(uint256 amount_, uint256 tokenId_)
We now detail each of these base functions.
RewardsDistributorDescription:
Sets ESCROW_VOTE_MANAGER and ESCROW_MANAGER as immutable addresses, used for authorization and lock ownership lookups.
Parameters:
escrowVoteManager_: The address of the escrow vote manager contract.
deposit(uint256 amount_, uint256 tokenId_)Description:
Called by the escrow vote manager to record that amount_ of tokens have been deposited for the lock represented by tokenId_ in the current epoch.
Increments the total supply and the lock owner’s balance for the current epoch.
withdraw(uint256 amount_, uint256 tokenId_)Description:
Called by the escrow vote manager to record that amount_ of tokens have been removed from the lock represented by tokenId_ in the current epoch.
Decrements the total supply and the lock owner’s balance for the current epoch.
getRewardTokensCount()Description:
Returns the length of the s_rewardTokens array, i.e., how many reward tokens the distributor currently recognizes.
Return:
uint256: number of recognized reward tokens.
earned(address owner_, address rewardToken_)Description:
Computes how many tokens of rewardToken_ the owner_ has earned across epochs since their last claim.
Iterates through epochs in weekly increments up to a maximum of 52 (1-year look-back) or until reaching the current epoch.
earnedByEpoch(address owner_, address rewardToken_, uint256 epoch_)Description:
Returns how many rewardToken_ tokens were earned by owner_ specifically in a single epoch.
Calculated as rewardPerToken(rewardToken_, epoch_) * s_balanceByOwnerAndEpoch[owner_][epoch_] / 1e18.
rewardPerToken(address rewardToken_, uint256 epoch_)Description:
Calculates the distribution ratio for rewardToken_ in a given epoch_.
If s_totalSupplyByEpoch[epoch_] is zero, it simply returns s_rewardAmountByTokenAndEpoch[rewardToken_][epoch_].
getReward(address owner_, address[] calldata rewardTokens_) (abstract)Description:
Abstract in the base RewardsDistributor. The child contract (IncentiveRewardsDistributor) provides the actual implementation.
Child’s implementation calls _getReward(...) internally after verifying authorization.
notifyRewardAmount(address rewardToken_, uint256 rewardAmount_) (abstract)Description:
Abstract method for adding new reward tokens. Child contract overrides this to add whitelisting checks or additional logic.
The base logic is available in _notifyRewardAmount(...) (see below).
_getReward(address owner_, address[] calldata rewardTokens_) (internal)Description:
The internal function that loops over rewardTokens_, calculates earned(...), updates s_lastRewardClaimByOwnerAndToken, and transfers the reward to owner_.
Finally, emits
_notifyRewardAmount(address sender_, address rewardToken_, uint256 rewardAmount_) (internal)Description:
Transfers rewardAmount_ of rewardToken_ from sender_ to this distributor.
Adds the difference in the contract’s balance to s_rewardAmountByTokenAndEpoch[rewardToken_][currentEpochStart]
Description:
Calls the RewardsDistributor constructor to set ESCROW_VOTE_MANAGER and ESCROW_MANAGER.
No additional logic besides inheritance.
getReward(address owner_, address[] calldata rewardTokens_)Description:
Implementation of getReward from both RewardsDistributor (abstract) and IIncentiveRewardsDistributor.
Allows the escrow vote manager to claim rewards for owner_.
notifyRewardAmount(address rewardToken_, uint256 rewardAmount_)Description:
Implementation of notifyRewardAmount from both RewardsDistributor (abstract) and IIncentiveRewardsDistributor.
First ensures rewardToken_ is whitelisted via
TokensDeposited(from, tokenId, amount)
TokensWithdrawn(from, tokenId, amount)
RewardNotified(from, token, epoch, amount)
InvalidRewardToken()
UnauthorizedAccess()
ZeroAmountProvided()
No new custom events or errors are introduced in IncentiveRewardsDistributor beyond what’s inherited.
IncentiveRewardsDistributor leverages the robust, epoch-based reward accounting system from RewardsDistributor to facilitate secure incentive distribution in the CrossCurve ecosystem, adding token whitelisting checks and limiting reward claims (getReward) to calls from the escrow vote manager. This design ensures:
Authorized Control: Only recognized and whitelisted tokens can be notified as rewards; only the escrow vote manager can trigger claims.
Accurate Reward Calculations: Inherits deposit/withdraw logic to track each user’s epoch-based balance.
Easy Integration: Conforms to the IIncentiveRewardsDistributor interface, providing consistent methods for reward notifications and claims across the system.
Together with the RewardsDistributor base contract, IncentiveRewardsDistributor offers a flexible, robust means of awarding incentive tokens in a multi-lock, epoch-based environment.
Leaderboard Section and Its Functionality
The accrual of points for the Airdrop Season 2 ended at 24:00 UTC on 30 September 2025.
To start working in the CrossCurve app, go to the Leaderboard section. There, click “Connect wallet” in the top right corner, choose a suitable wallet from the list, and confirm the connection, making sure you are on the original page https://app.crosscurve.fi/leaderboard.
After successfully connecting, you will see complete statistics of your earned points for participation in the EYWA Adventure Quest Season 2. The page displays the total number of earned points (updated every 24 hours at 00 UTC), the points received for completing basic and bonus tasks, statistics of your referrals.
Below, you will see the stats for your referrals, sorted by referral level and liquidity volume. It also shows your overall ranking, along with the number and volume of transactions. By switching between Season 1 (completed) and Season 2, you can see the stats for either of the seasons of the Airdrop.
By following the link Season 2 airdrop activities, you can learn about activities that allow you to accumulate points for the EYWA Season 2 airdrop:
Swaps on DEX
In this on-chain activity, you receive points for cross-chain swaps on our DEX, up to 250 points* per day. For completing a swap daily, you receive bonus points. Each new day starts at 00:00 UTC, with the points added within two hours of the transaction being verified on the blockchain
* from 12:30 UTC 18/06/2025 x3 points will be credited - up to 750 points per day
Early farming
This new program rewards users for providing liquidity. Just lock your liquidity into the and pools and receive rEYWA (reward EYWA) tokens. rEYWA is a nontransferable ERC-20 token that you will be able to exchange 1:1 for EYWA after the TGE. Rewards accrue based on the Early Farming program rules and depend on the volume of liquidity provided and the pool chosen. rEYWA has a 90-day vesting period from the moment it’s claimed. Claiming is available at any time, but one must wait until the vesting period is complete in order to be able to exchange all of his rEYWA for EYWA 1:1. The exchange is only possible after the TGE (Token Generation Event). Exchanging rEYWA before the vesting is complete will give him EYWA for only the rEYWA that has already vested, with the rest being returned to the EYWA DAO treasury. Read the program’s details
Introducing a new mechanic for accruing a reward for the daily completion of even one CrossCurve transaction. The new day starts at 00:00 UTC, and the points are accrued within two hours of the transaction’s confirmation on the blockchain.
Reward table for daily task completion
The daily limit of points one can receive for completing tasks is 250*. If a user had 240 points and completed a task worth 20 points, only 10 points will be accrued, equalling 250* in total. You can get points for two activity types:
* from 12:30 UTC 18/06/2025 x3 points will be credited - up to 750 points per day
• Cross-chain swaps in the tab (up to 200 points/swap**)
** from 12:30 UTC 18/06/2025 x3 points will be credited - up to 600 points/swap
• Deposits into the liquidity pool on the Fantom network in the tab ( up to 250 points/swap***)
*** from 12:30 UTC 18/06/2025 x3 points will be credited - up to 750 points/swap
You receive points for each cross-chain swap or LP in the tab.
** from 12:30 UTC 18/06/2025 all points are multiplied by x3.
1. After entering the desired swap amount in the Swap tab, the app will reflect the number of points you will receive within two hours of the transaction confirmation on-chain. In the Daily Reward field, you’ll the number of points accrued for the daily completion of transactions.
2. Clicking on info will give you complete information about your point accrual:
• 70 base points for a swap of $1,000 to $4,999
• 9,9 bonus points ( 3,3 for each $100 above $1,000)
• Total amount of base points earned per day
• Amount of points awaiting accrual within two hours
To quickly find the optimal swap route go to the Find best route tab, and select token and network by clicking on Select Network and Token.
After selecting token and network, enter the swap amount and click Find best route. The system will automatically find the best route for the swap.
Points are rewarded for providing liquidity (Deposit) in in the tab. Points are also accrued for bridging* tokens from one chain to another.
** from 12:30 UTC 18/06/2025 all points are multiplied by x3.
After entering the desired deposit amount in the tab, the app will show you the number of points you’ll receive for this deposit, within two hours of the transaction confirmation on-chain.
Through the referral system, you receive a part of the points from your referrals through our three-level program: 10% for the first level, 6% for the second level, and 4% for the third level. Points earned by each referral will be accrued once a day.
By clicking “Get referral link”, you will need to log in through your X account.
By clicking Connect Twitter, a new window will open for authorization through X. From there, click Authorize App.
After successful authorization, you need to follow EYWA account on X by clicking Follow EYWA.
Clicking Follow EYWA will open a new window to page. Click Follow.
After following EYWA on Twitter, your referral for copying will appear.
Clicking Post a Tweet and get Points will open a window to post the link in your account.
To publish, click Post.
EscrowManager is a smart contract that manages locked EYWA tokens, each represented by a unique ERC-721 NFT (sometimes referred to as a "veEYWA" token). Each lock NFT stores information about its locked token amount, unlock time, vesting wallets, and booster NFTs. The contract supports operations like depositing, boosting, extending, deboosting, and withdrawing locked tokens, while tracking voting power via time-based checkpoints and epochs. It integrates with an external vote manager contract for governance operations and a collection contract for booster NFTs.
Key Features:
ProposalManager is a governance contract built on OpenZeppelin’s Governor framework, incorporating additional logic for:
Protected Function Selectors: Certain function calls (on specific chain IDs and target addresses) are restricted to the contract owner. This prevents unauthorized calls to critical on-chain functionality within governance proposals.
uint256 public constant EPOCH_DURATION = 1 weeks;constructor() {
_disableInitializers();
}function initialize(
address owner_,
IERC20 eywa_,
IEscrowManager escrowManager_,
IEmissionManagerV1 emissionManager_
)
external
initializerfunction checkpoint() externalfunction claim(uint256 tokenId_) externalfunction claim(uint256[] calldata tokenIds_) externalfunction earned(uint256 tokenId_) external view returns (uint256)function _checkpoint() privatefunction _claim(uint256 tokenId_, uint256 lastCheckpointTime_) private returns (uint256)function _earned(
uint256 tokenId_,
uint256 lastCheckpointTime_
)
private
view
returns (
uint256 m_reward,
uint256 m_initialWeekCursor,
uint256 m_updatedWeekCursor
)m_supply = escrowManager.getPastTotalSupply(nextWeekTimestamp) (set to 1 if 0).Distributes m_reward += (m_balance * s_weeklyTokensDistributed[weekTimestamp]) / m_supply.
Increments m_updatedWeekCursor by EPOCH_DURATION.
Calculating earned rewards for each owner at specific epochs and enabling claim logic.
Declares and implements the IRewardsDistributor interface.
IIncentiveRewardsDistributor:
Extends IRewardsDistributor with additional constraints and methods (getReward & notifyRewardAmount restricted to certain checks).
Gives ownership and deposit/withdraw data for NFT-based locks.
Indirectly leveraged via RewardsDistributor functions for deposit/withdraw logic.
ReentrancyGuard (OpenZeppelin):
Inherited in RewardsDistributor to prevent re-entrant calls.
SafeERC20, IERC20 (OpenZeppelin):
Used for secure ERC20 transfers.
notifyRewardAmount(address rewardToken_, uint256 rewardAmount_) (abstract here, implemented in the child contract)
earned(address owner_, address rewardToken_) and earnedByEpoch(address owner_, address rewardToken_, uint256 epoch_)
rewardPerToken(address rewardToken_, uint256 epoch_)
Claiming Rewards:
getReward(address owner_, address[] calldata rewardTokens_) (abstract here, partially implemented in the child)
_getReward(address owner_, address[] calldata rewardTokens_) (internal)
Data Structures for Epoch Accounting and Balances:
Mappings storing how much each user has deposited per epoch, total supply per epoch, and how much reward is allocated per epoch.
escrowManager_: The address of the escrow manager contract.
Checks:
msg.sender == ESCROW_VOTE_MANAGER; otherwise UnauthorizedAccess().
Logic:
Queries the current epoch start via IEscrowVoteManagerV1(ESCROW_VOTE_MANAGER).currentEpochStart().
Increments s_totalSupplyByEpoch[m_currentEpochStart] by amount_.
Retrieves lock owner via IEscrowManager(ESCROW_MANAGER).ownerOf(tokenId_).
Increments s_balanceByOwnerAndEpoch[m_owner][m_currentEpochStart] by amount_.
Emits TokensDeposited(m_owner, tokenId_, amount_).
Checks:
msg.sender == ESCROW_VOTE_MANAGER; otherwise UnauthorizedAccess().
Logic:
Gets the current epoch start, as with deposit.
Decrements s_totalSupplyByEpoch[m_currentEpochStart] by amount_.
Finds lock owner and decreases s_balanceByOwnerAndEpoch[m_owner][m_currentEpochStart] by amount_.
Emits TokensWithdrawn(m_owner, tokenId_, amount_).
Returns:
(uint256 m_reward, uint256 m_lastRewardClaim): the total reward due and the final epoch boundary used for calculation.
Logic:
Checks if rewardToken_ is recognized in s_isRewardToken[rewardToken_]. If not, returns (0,0).
Locates the last claimed epoch timestamp for (owner_, rewardToken_).
Repeatedly calls earnedByEpoch(...) for each epoch from m_lastRewardClaim up to but not including currentEpochStart.
Summation is the total pending rewards.
Otherwise, divides that reward amount by the epoch’s total supply (scaled by 1e18).
Return:
uint256: The per-token reward ratio used to multiply by an owner’s deposit amount to get their share.
RewardsClaimed(owner_, token, amount)If s_initialIncentiveTimestamp == 0, sets it to the current epoch start.
Emits RewardNotified(sender_, rewardToken_, epoch, difference).
Calls _getReward(...) internally after checking msg.sender == ESCROW_VOTE_MANAGER.
s_isWhitelistedTokenIEscrowVoteManagerV1If the token is not recognized (!s_isRewardToken[rewardToken_]), checks the vote manager to see if it’s whitelisted; if so, it’s now added to s_rewardTokens.
If not whitelisted, reverts with NotWhitelisted().
Calls _notifyRewardAmount(msg.sender, rewardToken_, rewardAmount_) to handle actual fund transfer and epoch reward updates.
RewardsClaimed(from, token, amount)NotWhitelisted()Voting Power: Each lock corresponds to voting power that evolves over time. The contract records checkpoints of ownership and calculates voting weights using a dynamic rate-of-change approach.
Booster Mechanism: Boosters from the collection can increase a lock’s "coverage," thus effectively increasing its lock amount for voting power calculations.
Cooldown & Freeze Logic: After certain actions such as deboosting, token transfers may be temporarily frozen to prevent immediate re-deposit or locking manipulations.
Delegation Checks: The contract can integrate with a delegation manager to move voting power between addresses.
By implementing the IEscrowManager interface, the EscrowManager contract provides a consistent API for user and external contract interactions in the CrossCurve ecosystem.
ERC721Enumerable, ERC721 (OpenZeppelin): Provides standard ERC-721 NFT functionality with enumeration capabilities, enabling easy listing of all minted NFTs.
ERC721Holder (OpenZeppelin): Allows the contract to safely hold ERC-721 tokens (necessary when receiving booster NFTs).
ReentrancyGuard (OpenZeppelin): Mitigates re-entrant calls on state-changing functions.
SafeERC20, IERC20 (OpenZeppelin): Provides secure wrappers for ERC20 operations, ensuring safe token transfers.
External Interfaces:
IEscrowManager: The interface implemented by this contract, defining locking and booster logic.
IEscrowVoteManagerV1: The vote manager that tracks epochs, triggers freeze logic, and notifies about gauge rewards.
ICollection, IWalletFactory, IVestingWallet: Components in the ecosystem for NFT boosters, creating/managing vesting wallets, and bridging custom data.
IMetadataProviderV1: Supplies metadata URIs for NFTs.
VotingPowerHelper (Library): Used to compute historical voting power and supply based on stored checkpoints and rate-of-change data.
ATTACHMENTS_LIMIT = 100
Maximum number of attachments (vesting wallets or booster NFTs) allowed per lock.
EPOCH_DURATION = 1 weeks
Governs epoch-based calculations for voting power and lock logic.
MAXIMUM_LOCK_DURATION = 156 weeks
Maximum allowed lock duration in seconds (approximately 3 years).
MAXIMUM_NUMBER_OF_DELEGATES = 1024
Maximum delegates that can be tracked for a single account’s checkpoints.
SIGNED_MAXIMUM_LOCK_DURATION = 156 weeks
Signed integer equivalent for arithmetic purposes.
Rarity Multipliers and Capacities: Predefined numerators and capacity values for Common, Uncommon, Rare, Legendary, and Infinity NFT rarities.
PRECISION = 100,000
Scaling factor for multiplier-based calculations (e.g., coverage, booster effects).
Immutable Addresses:
ESCROW_VOTE_MANAGER (address): The escrow vote manager contract address.
DELEGATION_MANAGER (address): The delegation manager contract address.
EYWA (IERC20): The EYWA token used in locking.
COLLECTION (ICollection): The collection contract supporting booster NFTs.
WALLET_FACTORY (IWalletFactory): Factory contract for validating vesting wallets.
METADATA_PROVIDER (IMetadataProviderV1): Supplies off-chain metadata for NFTs.
s_nextTokenId (uint256)
The next NFT token ID to be minted.
s_epoch (uint256)
Tracks how many epochs have occurred, updated whenever lock states change significantly.
s_totalLocked (uint256)
Total EYWA tokens locked across all positions.
Lock and Booster Details:
_s_lockInfoByTokenId (mapping(uint256 => LockInfo)): Internal mapping of lock data.
s_pureLockAmountByTokenId, s_vestingWalletsLockAmountByTokenId: Track base token amounts and vesting wallet contributions.
s_currentCoverageByTokenId: Booster coverage for each lock.
s_boostersByTokenId, s_boostersByTokenIdAndRarity: Maintain sets of booster NFT IDs by token ID and rarity.
Checkpointing and Voting:
s_checkpointsNumberByAccount (mapping(address => uint32)): Number of checkpoints for each account.
s_checkpoints (mapping(address => mapping(uint32 => Checkpoint))): Account checkpoints listing owned lock NFTs at different times.
s_ownershipChangeBlockNumberByTokenId (mapping(uint256 => uint256)): Block number of the last ownership change for each NFT (prevents double-voting in the same block).
s_rateOfChangeByUnlockTime (mapping(uint256 => int128)): Tracks changes in voting power at specific unlock times.
s_hasVotedByTokenId (mapping(uint256 => bool)): Whether a token has voted in the current epoch.
s_hasVotedByEpochAndTokenId (mapping(uint256 => mapping(uint256 => bool))): Tracks vote status for each token in each epoch.
s_votingPowerPointByEpoch (mapping(uint256 => VotingPowerPoint)): Stores aggregated voting power changes per epoch.
s_votingPowerPointByTokenIdAndEpoch (mapping(uint256 => VotingPowerPoint[1000000000])): Voting power data for each token ID across epochs.
Deboost and Freeze Logic:
s_lastDeboostTimestampByTokenId (mapping(uint256 => uint256)): Records the last time a token was deboosted, used to freeze subsequent transfers.
Description: Deploys the EscrowManager, sets immutable addresses for the escrow vote manager, delegation manager, EYWA token, collection, wallet factory, and metadata provider, and initializes the NFT name and symbol.
Description:
Creates a lock by transferring lockAmount_ of EYWA from the caller, locking it for lockDuration_ (rounded down to epoch boundaries). Mints an NFT for recipient_.
Description: Creates a lock by transferring tokens from multiple vesting wallets owned by the caller, then mints an NFT lock. Each vesting wallet's beneficiary must match the caller.
Description:
Creates a lock using tokens associated with the given collection token IDs. Collects vesting wallets pinned to those NFTs, locks their balances, and automatically applies boosters via _modifyBoost.
Description:
Adds extra EYWA to an existing lock. Requires caller authorization (_checkAuthorized).
Description: Adds EYWA to an existing lock on behalf of the owner, without caller checks.
Description: Associates additional booster NFTs with a lock, increasing its coverage and potentially its voting power. Booster NFTs may also bring vesting wallets if pinned.
Description:
Removes booster NFTs from a lock. Verifies that the token hasn't voted in the current epoch. Records the block timestamp in s_lastDeboostTimestampByTokenId to freeze transfers for a defined period.
Description: Withdraws the tokens from an expired lock, returning booster NFTs, transferring vesting wallets, and burning the lock NFT. The caller must be authorized.
Events:
Emits LockWithdrawn(recipient, tokenId, value) upon completion.
Description:
Extends the lock duration to a new unlockTime. Must be strictly greater than the current one. Updates voting power.
Description:
Only callable by ESCROW_VOTE_MANAGER. Marks a token as having voted or not.
Description:
Only callable by ESCROW_VOTE_MANAGER. Records that a token has voted (or not) in the current epoch.
Description:
Called by DELEGATION_MANAGER to transfer voting power if delegated. Ensures the token exists.
Description: Returns the lock’s current amount, unlock timestamp, and associated vesting wallets.
Description: Reports how many seconds remain until a token can be transferred again after deboost. Returns 0 if the freeze period has elapsed.
Description:
Retrieves the checkpoint at index_ for account_, listing token ownership at that historical checkpoint.
Description:
Calculates an account’s total voting power at a previous timestamp_, summing the power of all tokens they held at that time.
Description: Returns the total voting power across all locks at the current time.
Description:
Returns the total voting power at a specific timestamp_. Uses the VotingPowerHelper for historical calculations.
Description:
Computes a single token’s voting power at a past timestamp_, factoring in rate-of-change data.
Description:
Lists all booster NFT IDs currently enhancing the lock identified by tokenId_.
Description:
Checks if spender_ is permitted (owner, approved address, or operator) to manage the NFT for tokenId_.
Description:
Returns true if an NFT for tokenId_ has been minted (i.e., the lock exists).
Signature:
Description: Core logic for creating a new lock. Mints an NFT, stores lock info, and transfers tokens or vesting wallets if needed.
Signature:
Description: Adds more EYWA to a lock, updating voting power calculations.
Signature:
Description: Adds or removes booster NFTs to/from a lock. Adjusts coverage and recalculates voting power accordingly.
Signature:
Description: Recomputes and stores new voting power points whenever a lock’s amount or unlock time changes. Adjusts historical checkpoints and the global epoch.
Signature:
Description:
Reassigns voting power from from_ to to_ if the NFT’s ownership changes. Creates or updates checkpoints for both addresses.
Signature:
Description: Clears all references and data for a withdrawn or burned lock, freeing storage.
Signature:
Description: Helper to find or create the index for a checkpoint at the current timestamp for a given account.
Signature:
Description: Calculates the final lock amount after factoring in booster NFT coverage and rarity-based multipliers. If coverage exceeds lock amount, the algorithm partial-applies boosters in descending rarity.
Emitted When: A user withdraws tokens from an expired lock. The NFT is burned, and booster NFTs/vesting wallets are returned.
InvalidBeneficiary()
InvalidVestingWallet()
InvalidLockDuration()
InvalidLockAmount()
InvalidCollectionTokenId(uint256 tokenId)
InvalidArrayLength()
InvalidRarity()
NonExistentToken()
ExtendedUnlockTimeMustBeGreater()
AttachmentsLimitExceeded()
LockStillActive()
LockCurrentlyVoting()
MaximumNumberOfDelegatesExceeded()
BoostModificationAfterVoting()
UnauthorizedCaller()
TransferFrozenDueToDeboost()
These errors ensure that contract rules regarding lock durations, amounts, boosters, freeze periods, and ownership checks are strictly enforced.
EscrowManager provides a robust system for locking EYWA tokens in exchange for NFT-based positions (veEYWA). Each lock can combine direct token transfers, vesting wallets, and booster NFTs, forming dynamic voting power that evolves over time. Freeze periods after deboosts and careful checkpointing logic protect against immediate manipulations of lock amounts and ownership. Through a clear interface defined in IEscrowManager, external ecosystem components (e.g., delegation managers, vote managers, NFT collections) can seamlessly integrate with this locking mechanism to support governance, incentive distribution, and user engagement within the CrossCurve platform.
Emission Manager (IEmissionManagerV1): Supplies emission epochs and total reward amounts.
Rewards Distributor Factory (IRewardsDistributorFactoryV1): Deploys incentive reward distributor contracts for new gauges.
Gauge Factory (IGaugeFactoryV1): Deploys gauge contracts, which are used to distribute rewards based on votes.
Reward Distributors (IRewardsDistributor): Handle depositing and withdrawing of votes and distributing claimable incentives.
The contract also includes logic for:
Voting with multiple token IDs: A user can cast votes across multiple locks (NFTs) for multiple pools.
Transfer Freeze after Deboost: Adds a cooldown period preventing NFT transfers after a lock has been deboosted in the Escrow Manager.
Gauge Lifecycle Management: Owners can create, kill, or revive gauges.
Reward Distribution: Accumulates gauge rewards and distributes them after each epoch.
By implementing IEscrowVoteManagerV1, EscrowVoteManagerV1 provides a standardized API for gauge-based governance interactions in the CrossCurve ecosystem.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality under the UUPS proxy pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Manages ownership, allowing only the owner to modify critical parameters and authorize upgrades.
IEscrowVoteManagerV1:
Defines core methods (e.g., vote, createGauge, distributeRewardsForMultipleGauges) and events for this contract.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Handles secure ERC20 operations for distributing and approving token transfers.
Math (OpenZeppelin): Provides utility math functions, e.g., Math.max.
IEscrowManager: Holds locked token data and checks voting power and freeze logic.
IRewardsDistributorFactoryV1, IGaugeFactoryV1: Deploy new reward distributors and gauge contracts, respectively.
IGaugeV1: Interface for a gauge contract that can receive reward notifications (notifyRewardAmount).
IEmissionManagerV1: Informs about epoch starts and ensures updated weekly distributions.
EPOCH_DURATION: Duration of each emission/gauge epoch (1 week).
PRECISION: Scaling factor (1e18) for reward calculations and distribution indexes.
s_transferFreezeAfterDeboost (uint256)
Duration (in seconds) that locks are non-transferable after a deboost in the Escrow Manager.
s_emissionManager (address)
Address of the emission manager contract, which calls this manager to notify new rewards.
s_eywa (address)
Address of the EYWA token used for gauge rewards.
s_escrowManager (IEscrowManager)
Reference to the contract that manages locked tokens (NFT-based locks).
s_rewardsDistributorFactory (IRewardsDistributorFactoryV1)
Creates new rewards distributor contracts for gauges.
s_gaugeFactory (IGaugeFactoryV1)
Creates new gauge contracts.
_s_distributionIndex (uint256)
A global distribution index used to compute new reward distribution shares after the emission manager notifies reward amounts.
s_pools (address[])
An array of pool addresses that have gauges.
s_gaugeByPool (mapping(address => address))
Maps a pool address to its gauge contract address.
s_poolByGauge (mapping(address => address))
Reverse map: gauge address to the corresponding pool address.
s_incentiveRewardsDistributorByGauge (mapping(address => address))
Tracks which incentive rewards distributor belongs to which gauge.
s_votesByEpochAndPool (mapping(uint256 => mapping(address => uint256)))
Records how many votes each pool has received in a given epoch (keyed by epoch start timestamp).
s_claimableRewardsByGauge (mapping(address => uint256))
Shows how many EYWA tokens each gauge can claim, waiting to be distributed.
s_lastDistributionTimestampByGauge (mapping(address => uint256))
Timestamp of the most recent reward distribution for each gauge.
s_isGauge (mapping(address => bool))
Indicates if an address is recognized as a gauge.
s_isWhitelistedToken (mapping(address => bool))
Tracks which tokens are whitelisted for reward distributions and voting.
s_isActiveGauge (mapping(address => bool))
If true, the gauge is active and can receive new rewards.
s_usedVotesByTokenId (mapping(uint256 => uint256))
How many votes a lock (NFT) has allocated.
s_lastVotedTimestampByTokenId (mapping(uint256 => uint256))
Timestamp of the last time a token ID voted, used to reset or poke votes.
s_votedPoolsByTokenId (mapping(uint256 => address[]))
List of pools each token ID is currently voting for.
s_totalVotesByEpoch (mapping(uint256 => uint256))
Cumulative votes across all pools in a given epoch.
s_votesByTokenIdAndPool (mapping(uint256 => mapping(address => uint256)))
Number of votes allocated by a specific token ID to a particular pool.
_s_supplyDistributionIndex (mapping(address => uint256))
Per-gauge distribution index to track how much of the global distribution index the gauge has accounted for.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
Description: Configures ownership, references, and initial state:
Sets s_transferFreezeAfterDeboost to 4 hours initially.
References the emission manager, escrow manager, gauge/rewards distributor factories, and whitelists initial tokens.
Description:
Updates the freeze period (in seconds) that applies after a deboost in Escrow Manager. This restricts NFT transfers for transferFreezeAfterDeboost_ seconds.
Events:
Emits TransferFreezeAfterDeboostUpdated(oldDuration, newDuration).
Description: Creates a new gauge for a specified pool by:
Deploying an incentive rewards distributor via s_rewardsDistributorFactory.
Deploying a gauge contract via s_gaugeFactory.
Tracking the new gauge and marking it as active.
Checks:
Ensures the pool does not already have a gauge.
Events:
Emits GaugeCreated(pool_, gauge, incentiveRewardsDistributor).
Description: Deactivates a gauge so it stops receiving future rewards. Does not remove votes or claimable rewards; simply marks it inactive.
Checks:
s_isActiveGauge[gauge_] must be true.
Events:
Emits GaugeKilled(gauge_).
Description: Reactivates a previously killed gauge, allowing it to receive rewards again.
Checks:
s_isActiveGauge[gauge_] must be false.
Events:
Emits GaugeRevived(gauge_).
Description: Updates whether tokens are whitelisted for reward distribution. Only callable by the contract owner. Checks input array lengths.
Events:
Emits WhitelistStatusUpdatedForTokens(operator, tokens_, statuses_).
Description: Allows a user to cast votes for multiple token IDs across multiple pools. For each token ID:
Authorizes caller via IEscrowManager.checkAuthorized.
Validates array lengths for pools and weights.
Performs _vote(...) to reset old votes, allocate new votes, and update vote counts.
Description: Removes all existing votes for a given token ID, setting them to zero. The caller must be authorized. Updates the token’s last vote timestamp.
Description:
Recalculates (re-casts) votes for a token ID based on updated voting power without changing the vote distribution pattern. The function still calls _vote(...) internally using the same pools and weights previously allocated.
claimIncentives(address[] calldata incentiveRewardsDistributors_, address[][] calldata rewardTokens_)Description:
Claims incentives for the caller from multiple rewards distributors. Each distributor has a list of reward tokens. Forwards the call to IRewardsDistributor.getReward.
Description:
Only callable by s_emissionManager. Increments _s_distributionIndex by an amount proportional to rewardAmount_ / totalVotesInPreviousEpoch. If no votes or unauthorized call, reverts.
Events:
Emits RewardNotified(rewardAmount_).
Description:
Triggers an epoch update in the emission manager, then calls _distributeRewards(...) for each gauge in gauges_.
Description:
Also triggers an emission manager epoch update, then iterates through s_pools[start_ ... end_] to distribute rewards to each gauge.
Description:
Returns the number of pools (and thus gauges) tracked in s_pools.
Description:
Returns the next epoch’s start time as s_currentEpochStart + EPOCH_DURATION from the emission manager.
Description: Returns the current epoch’s start time from the emission manager.
Description: Restricts contract upgrades to the owner.
Description: Handles the actual voting steps for a single token ID:
Calls _reset(...) to remove existing votes.
Proportionally allocates votingPower_ across pools based on weights_.
Updates s_votesByEpochAndPool, s_votesByTokenIdAndPool, and s_votedPoolsByTokenId.
Deposits votes into the associated gauge’s incentive rewards distributor.
Tracks total votes used by the token ID (s_usedVotesByTokenId).
Informs escrow manager the token has voted.
Events:
VoteCast on each pool voted for.
Description:
Clears existing votes for tokenId_ by:
Withdrawing votes from all previously voted pools (if the token voted in the current epoch).
Adjusting s_votesByEpochAndPool and s_votesByTokenIdAndPool.
Updating the total votes for the epoch.
Marking the token as not voted in the escrow manager.
Emitting VotesAbstained.
Description: Distributes claimable EYWA tokens to a specified gauge. If the gauge is inactive, does nothing. Otherwise:
Calls _updateRewardIndexForGauge(...).
Notifies the gauge of claimable rewards via notifyRewardAmount.
Events:
RewardsDistributed after successful distribution.
Description:
Calculates how many new tokens a gauge can claim using the global distribution index. If there were votes in the previous epoch (currentEpochStart_ - EPOCH_DURATION), the gauge's share of _s_distributionIndex is updated, and claimable rewards are added to s_claimableRewardsByGauge[gauge_].
TransferFreezeAfterDeboostUpdated(oldDuration, newDuration)
Emitted when the freeze period is changed.
GaugeCreated(pool, gauge, incentiveRewardsDistributor)
Emitted upon successful gauge creation.
GaugeKilled(gauge), GaugeRevived(gauge)
Emitted when a gauge is deactivated or reactivated.
WhitelistStatusUpdatedForTokens(operator, tokens, statuses)
Shows updated whitelist status for multiple tokens.
RewardNotified(rewardAmount)
Occurs when the emission manager notifies a new reward sum.
VoteCast(voter, pool, tokenId, votes)
Occurs for each pool a token ID votes for.
VotesAbstained(voter, pool, tokenId, votes)
Occurs when votes are reset/removed for a given pool.
RewardsDistributed(distributor, gauge, rewardAmount)
Shows distribution of accumulated rewards to a gauge.
GaugeDoesNotExist()
Thrown if a user tries to vote for a gauge that is not known (no gauge for that pool).
GaugeAlreadyExists()
Thrown when creating a gauge for a pool that already has one.
GaugeNotActive()
Thrown if an action (like voting or distributing) is attempted on an inactive gauge.
GaugeAlreadyActive()
Thrown if reactivating a gauge that is already active.
UnauthorizedAccess()
Thrown if a non-authorized caller tries to vote or manage votes.
InvalidArrayLengths()
Thrown if arrays for tokenIds_, pools_, or weights_ do not match in length.
ZeroEntry()
Thrown if some operation results in zero (e.g., zero votes allocated to a pool).
AlreadyVoted()
Not used in current logic, but defined in the interface.
ProtectedFunctionSelectorUsed()
Not used here (relates to proposal manager).
InvalidSliceParameters()
Not used here, pertains to slicing logic in other modules.
EscrowVoteManagerV1 orchestrates multi-token, multi-pool voting within the CrossCurve ecosystem. By coordinating gauges, incentive reward distribution, epoch-based reward notifications from the emission manager, and freeze logic from the escrow manager, it ensures a secure, transparent mechanism for users to direct token emissions to liquidity pools and other incentive-based programs. With features like deboost freeze periods and gauge lifecycle control, the contract provides flexible governance and reward distribution for token holders.
IncentiveRewardsDistributor (Concrete)
└── RewardsDistributor (Abstract)
└── IRewardsDistributor (Interface)constructor(address escrowVoteManager_, address escrowManager_) {
ESCROW_VOTE_MANAGER = escrowVoteManager_;
ESCROW_MANAGER = escrowManager_;
}function deposit(uint256 amount_, uint256 tokenId_) externalfunction withdraw(uint256 amount_, uint256 tokenId_) externalfunction getRewardTokensCount() external view returns (uint256)function earned(address owner_, address rewardToken_) public view returns (uint256, uint256)function earnedByEpoch(address owner_, address rewardToken_, uint256 epoch_) public view returns (uint256)function rewardPerToken(address rewardToken_, uint256 epoch_) public view returns (uint256)function getReward(address owner_, address[] calldata rewardTokens_) external virtual;function notifyRewardAmount(address rewardToken_, uint256 rewardAmount_) external virtual;function _getReward(address owner_, address[] calldata rewardTokens_) internalfunction _notifyRewardAmount(address sender_, address rewardToken_, uint256 rewardAmount_) internalconstructor(address escrowVoteManager_, address escrowManager_)
RewardsDistributor(escrowVoteManager_, escrowManager_)
{}function getReward(
address owner_,
address[] calldata rewardTokens_
)
external
override (RewardsDistributor, IIncentiveRewardsDistributor)
nonReentrantfunction notifyRewardAmount(
address rewardToken_,
uint256 rewardAmount_
)
external
override (RewardsDistributor, IIncentiveRewardsDistributor)
nonReentrantconstructor(
address escrowVoteManager_,
address delegationManager_,
IERC20 eywa_,
ICollection collection_,
IWalletFactory walletFactory_,
IMetadataProviderV1 metadataProvider_
)
ERC721("EYWA DAO NFT", "veEYWA")
{
...
}function createLock(
uint256 lockAmount_,
uint256 lockDuration_,
address recipient_
)
external
nonReentrantfunction createLock(
uint256 lockDuration_,
address recipient_,
address[] calldata vestingWallets_
)
external
nonReentrantfunction createLock(
uint256 lockDuration_,
address recipient_,
uint256[] calldata collectionTokenIds_
)
external
nonReentrantfunction deposit(uint256 tokenId_, uint256 lockAmount_) external nonReentrantfunction depositFor(uint256 tokenId_, uint256 lockAmount_) external nonReentrantfunction boost(uint256 tokenId_, uint256[] calldata collectionTokenIds_) external nonReentrantfunction deboost(uint256 tokenId_, uint256[] calldata collectionTokenIds_) external nonReentrantfunction withdraw(uint256 tokenId_) external nonReentrantfunction extend(uint256 tokenId_, uint256 lockDuration_) external nonReentrantfunction setVoteStatus(uint256 tokenId_, bool status_) externalfunction registerTokenVote(uint256 tokenId_, bool status_) externalfunction moveVotes(uint256 tokenId_, address from_, address to_) externalfunction getLockInfoByTokenId(uint256 tokenId_)
external
view
returns (
int128 lockAmount_,
uint256 unlockTime_,
address[] memory vestingWallets_
)function getRemainingFreezeTimeByTokenId(uint256 tokenId_) external view returns (uint256)function getCheckpoint(address account_, uint32 index_) external view returns (Checkpoint memory)function getPastVotes(address account_, uint256 timestamp_) external view returns (uint256 votes_)function getTotalSupply() external view returns (uint256)function getPastTotalSupply(uint256 timestamp_) external view returns (uint256)function getPastVotesByTokenId(uint256 tokenId_, uint256 timestamp_) external view returns (uint256)function getBoostersByTokenId(uint256 tokenId_) external view returns (uint256[] memory boosters_)function checkAuthorized(address owner_, address spender_, uint256 tokenId_) external view returns (bool)function exists(uint256 tokenId_) external view returns (bool)function _createLock(
uint256 lockAmount_,
uint256 lockDuration_,
address recipient_,
address[] memory vestingWallets_,
LockModificationType lockModificationType_
) privatefunction _deposit(uint256 tokenId_, uint256 lockAmount_) privatefunction _modifyBoost(
uint256 tokenId_,
uint256[] memory collectionTokenIds_,
LockModificationType lockModificationType_
) privatefunction _updateLock(
uint256 tokenId_,
LockInfo memory previousLockInfo_,
LockInfo memory currentLockInfo_
) privatefunction _moveVotes(uint256 tokenId_, address from_, address to_) privatefunction _clearStorage(uint256 tokenId_) privatefunction _findCheckpoint(address account_) private view returns (uint32)function _calculateModifiedLockAmount(
uint256 tokenId_,
uint256 coverage_,
uint256 lockAmount_
) private view returns (uint256)uint256 public constant EPOCH_DURATION = 1 weeks;
uint256 public constant PRECISION = 1e18;constructor() {
_disableInitializers();
}function initialize(
address owner_,
address emissionManager_,
address eywa_,
IEscrowManager escrowManager_,
IRewardsDistributorFactoryV1 rewardsDistributorFactory_,
IGaugeFactoryV1 gaugeFactory_,
address[] calldata whitelistedTokens_
) external initializerfunction updateTransferFreezeAfterDeboost(uint256 transferFreezeAfterDeboost_) external onlyOwnerfunction createGauge(
address pool_,
IDistributionCreator.CampaignParameters calldata campaignParameters_
) external onlyOwnerfunction killGauge(address gauge_) external onlyOwnerfunction reviveGauge(address gauge_) external onlyOwnerfunction setWhitelistStatusForTokens(
address[] calldata tokens_,
bool[] calldata statuses_
) external onlyOwnerfunction vote(
uint256[] calldata tokenIds_,
address[][] calldata pools_,
uint256[][] calldata weights_
) externalfunction reset(uint256 tokenId_) externalfunction poke(uint256 tokenId_) externalfunction claimIncentives(
address[] calldata incentiveRewardsDistributors_,
address[][] calldata rewardTokens_
) externalfunction notifyRewardAmount(uint256 rewardAmount_) externalfunction distributeRewardsForMultipleGauges(address[] calldata gauges_) externalfunction distributeRewardsForGaugesInRange(uint256 start_, uint256 end_) externalfunction getPoolsCount() external view returns (uint256)function nextEpochStart() external view returns (uint256)function currentEpochStart() external view returns (uint256)function _authorizeUpgrade(address) internal override onlyOwnerfunction _vote(
uint256 tokenId_,
uint256 votingPower_,
address[] memory pools_,
uint256[] memory weights_
) privatefunction _reset(uint256 tokenId_) privatefunction _distributeRewards(address gauge_, uint256 currentEpochStart_) privatefunction _updateRewardIndexForGauge(address gauge_, uint256 currentEpochStart_) privateLlamaville Mini App
Your activity in the Llamaville app allows you to farm cryptodollars and receive new social and on-chain activity tasks as part of the 2nd season of our Airdrop program. Llamaville is a complete educational app. It immerses users into the world of crypto, allowing them to go through all the stages of growth, from fear and greed to success — without risking any real losses. The app is accessible only by invite, which you can request in EYWA’s official Telegram and Discord communities
Referral activity
The 3-level referral program allows you to receive points for the activity of your friends. Generate your personal referral link by clicking Get your Referral link and invite others to join the program. You will instantly get a portion of the points as they earn them: 10% for level 1 referrals, 6% for level 2, and 4% for level 3. You can find more details about this program below.
7
100
$5,000 and up
200 points
-
1
10
2
20
3
30
4
40
5
60
6
$5 to $49
4.2 points
0.33 points for each $5 above $5
$50 to $99
7 points
1.8 points for each $5 above $50
$100 to $999
25 points
0.5 points for each $10 above $100
$1,000 to $4,999
70 points
$700 to $999
7 points
-
$1,000 to $9,999
10 points
0.5 for each $100 above the first $1,000
$10,000 to $49,999
55 points
4,9 for each $1,000 above $10,000
$50,000 and up
250 points


80
3.3 points for each $100 above $1000
-

Cross-Chain Awareness: Maintains a set of valid chain IDs for bridging proposals, allowing secure multi-chain governance actions when using the bridge.
Custom Quorum Rules: Allows the owner to adjust the quorum fraction within set bounds (25%–80%).
The contract also integrates with a Calldata Helper (CALLDATA_HELPER) to decode function selectors from the bridging calls. By extending Governor, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl, and Ownable, ProposalManager offers a robust on-chain DAO mechanism with time-locked execution, vote counting, adjustable quorum, and protective measures for crucial function selectors.
Governor (OpenZeppelin): Base contract for on-chain governance, offering functionalities such as proposal creation, voting, proposal states, etc.
GovernorCountingSimple (OpenZeppelin): Implements a simple vote counting mechanism: For, Against, and Abstain.
GovernorVotes (OpenZeppelin):
Integrates an IVotes token (in this case, an escrow manager providing voting power) for calculating a user’s votes at proposal snapshot blocks.
GovernorVotesQuorumFraction (OpenZeppelin): Defines quorum as a fraction of the total supply of the governance token. The fraction is adjustable by the contract’s owner within defined limits.
GovernorTimelockControl (OpenZeppelin):
Integrates a TimelockController for executing proposals after a governance-defined delay.
Ownable (OpenZeppelin): Provides basic ownership functionality, allowing the owner to perform restricted actions (e.g., adjusting quorum fraction, managing chain IDs/selectors).
IProposalManager (Custom): Declares additional functions, errors, and events specifically for managing cross-chain or bridging-based proposals, including protected selectors.
Additional External References:
ICalldataHelperV1 (CALLDATA_HELPER): A contract that decodes selectors from proposal call data, used for identifying protected function selectors in bridging calls.
EnumerableSet (OpenZeppelin): Used to store a set of valid chain IDs, ensuring efficient addition, removal, and existence checks.
MINIMUM_QUORUM_NUMERATOR (25): Minimum permissible quorum fraction (25%).
MAXIMUM_QUORUM_NUMERATOR (80): Maximum permissible quorum fraction (80%).
CALLDATA_HELPER (ICalldataHelperV1 immutable)
The address of a helper contract used to decode function selectors for bridging calls. Set in the constructor and cannot be changed.
s_bridge (address)
The address of the bridge contract used for cross-chain proposals or calls. Initially set in the constructor, can be updated by setBridge.
_chainIds (EnumerableSet.UintSet)
A private set of valid chain IDs recognized by the contract. The owner can add or remove chain IDs via addChainId / removeChainId.
s_protectedSelectorsByChainIdAndTarget (mapping(uint256 => mapping(address => bytes4[])))
Stores arrays of protected function selectors for each (chainId, target) pair.
s_isProtectedSelector (mapping(uint256 => mapping(address => mapping(bytes4 => bool))))
A quick boolean lookup indicating if a particular function selector is protected on a given chainId and target address.
Parameters:
escrowManager_: An IVotes-compliant contract (e.g., an escrow manager) used for vote calculations.
timelock_: The TimelockController contract address used to queue and execute proposals after a time delay.
calldataHelper_: The helper contract for decoding function selectors in bridging calls.
owner_: Address designated as the owner of this contract (can set quorum fraction, manage chain IDs, etc.).
bridge_: The initial address of the cross-chain bridge.
Logic and Effects:
Initializes the underlying Governor modules:
Governor("EYWA DAO") sets the governor name.
Description:
Updates the s_bridge address used for bridging calls. Only callable by the contract owner.
Parameters:
bridge_: The new bridge contract address.
Events:
BridgeUpdated(oldBridge, newBridge) logs the address change.
Description:
Adds a new chain ID to _chainIds. If the chain ID already exists, it reverts.
Checks:
_chainIds.add(chainId_) must return true, otherwise reverts with ChainIdAlreadyExists(chainId_).
Description:
Removes an existing chain ID from _chainIds. If the chain ID does not exist, it reverts.
Checks:
_chainIds.remove(chainId_) must return true, otherwise reverts with ChainIdDoesNotExist(chainId_).
Description:
Returns the number of chain IDs stored in _chainIds.
Return:
uint256: The length of _chainIds.
Description:
Retrieves a chain ID from _chainIds by index_.
Return:
uint256: The chain ID at the specified index.
Description:
Marks a function selector (selector_) as protected on a particular chainId_ and target_. If the chain ID doesn’t exist or the selector is already protected, it reverts.
Events & Checks:
Must have _chainIds.contains(chainId_), otherwise InvalidChainId(...).
If s_isProtectedSelector[chainId_][target_][selector_] is true, reverts with SelectorAlreadyExists(...).
Adds the selector to s_protectedSelectorsByChainIdAndTarget[chainId_][target_] and sets s_isProtectedSelector[chainId_][target_][selector_] = true.
Description:
Removes a protected function selector from s_protectedSelectorsByChainIdAndTarget. If the chain ID isn’t recognized or the selector isn’t actually protected, it reverts.
Logic:
Ensures chainId_ is valid in _chainIds.
Checks if s_isProtectedSelector[chainId_][target_][selector_] == true; otherwise reverts with SelectorDoesNotExist(...).
Searches in the array s_protectedSelectorsByChainIdAndTarget[chainId_][target_], removes the entry by swapping the last element, then popping the array.
Deletes s_isProtectedSelector[chainId_][target_][selector_].
Description:
An override from GovernorVotesQuorumFraction that checks if the new quorum fraction is within [MINIMUM_QUORUM_NUMERATOR, MAXIMUM_QUORUM_NUMERATOR]. Otherwise reverts with GovernorInvalidQuorumFraction(...).
Description: An override from GovernorTimelockControl. This function does nothing here (the timelock is set in the constructor).
Description:
Creates a new proposal. Before creation, the contract calls _checkSelectors(...) to see if any protected calls are included in calldatas_. If protected calls are found but the proposer is not the owner, it reverts with ProtectedFunctionSelectorUsed().
After checking, it calls super.propose(...) to proceed with the standard Governor proposal workflow.
Parameters:
targets_, values_, calldatas_: Arrays specifying which contracts and functions to call, with how much ETH, plus the function data.
description_: A string describing the proposal.
Return:
uint256: The ID of the newly created proposal.
Description:
Returns the current timestamp as a uint48. Used by the governance system for time-related logic.
Description: Returns the current state of a proposal (Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, or Executed), integrating timelock considerations.
Description:
Calculates the number of votes required for quorum at a given timepoint_, i.e., (totalSupplyAt(timepoint_) * quorumNumerator(timepoint_)) / quorumDenominator().
Description:
Returns "mode=timestamp", indicating that block timestamps (instead of block numbers) are used for governance timing.
These standard overrides define:
proposalThreshold(): 2_500e18 — minimum voting power needed to create a proposal.
votingDelay(): 2 days — time between proposal creation and the start of voting.
votingPeriod(): 5 days — how long votes are accepted.
proposalNeedsQueuing(...): returns true, indicating proposals must be queued in the timelock after passing, before execution.
Description:
Iterates over targets_ and associated calldatas_, extracting the function selector for each. Then checks if it is among the protected selectors for the given chain ID (block.chainid) or if the target is the s_bridge address.
If any call uses a protected selector and proposalCreator_ is not the contract owner, reverts with ProtectedFunctionSelectorUsed().
Parameters:
proposalCreator_: The address that created the proposal.
targets_: The array of target contract addresses.
Logic:
If targets_[i] equals s_bridge, decodes further with CALLDATA_HELPER.decode(...) to find (m_calldata, m_target, m_chainId). Then extracts the first 4 bytes (selector) from m_calldata.
These are standard overrides from GovernorTimelockControl that handle queueing, executing, and canceling proposals in the timelock. The _executeOperations override also calls _checkSelectors(...) again before executing the proposal.
BridgeUpdated(address indexed oldBridge, address indexed newBridge)
Emitted when the bridge address changes via setBridge.
No additional custom events are defined besides those in the IProposalManager interface and standard Governor events.
From IProposalManager, we have:
ChainIdAlreadyExists(uint256 chainId)
ChainIdDoesNotExist(uint256 chainId)
SelectorAlreadyExists(bytes4 selector)
SelectorDoesNotExist(bytes4 selector)
InvalidChainId(uint256 chainId)
ProtectedFunctionSelectorUsed()
GovernorInvalidQuorumFraction(uint256 newQuorumNumerator, uint256 quorumDenominator) (part of GovernorVotesQuorumFraction logic)
ProposalManager extends and customizes OpenZeppelin’s Governor to cater to CrossCurve DAO’s multi-chain governance needs. Through protective measures (_checkSelectors), it guards certain function calls on specific chain IDs and target addresses, ensuring only the contract owner can propose them. Additionally, it manages a dynamic range of acceptable quorum fractions and integrates with a TimelockController for secure, time-delayed proposal execution. By combining these features with ICalldataHelperV1 for decoding bridging calls, ProposalManager offers a flexible yet secure governance solution for cross-chain proposals in the CrossCurve ecosystem.
uint256 public constant MINIMUM_QUORUM_NUMERATOR = 25;
uint256 public constant MAXIMUM_QUORUM_NUMERATOR = 80;constructor(
IVotes escrowManager_,
TimelockController timelock_,
ICalldataHelperV1 calldataHelper_,
address owner_,
address bridge_
)
Governor("EYWA DAO")
GovernorVotes(escrowManager_)
GovernorVotesQuorumFraction(50)
GovernorTimelockControl(timelock_)
Ownable(owner_)
{
CALLDATA_HELPER = calldataHelper_;
s_bridge = bridge_;
}function setBridge(address bridge_) external onlyOwnerfunction addChainId(uint256 chainId_) external onlyOwnerfunction removeChainId(uint256 chainId_) external onlyOwnerfunction getChainIdsLength() external view returns (uint256)function getChainIdAtIndex(uint256 index_) external view returns (uint256)function addProtectedSelector(uint256 chainId_, address target_, bytes4 selector_) external onlyOwnerfunction removeProtectedSelector(uint256 chainId_, address target_, bytes4 selector_) external onlyOwnerfunction updateQuorumNumerator(uint256 quorumNumerator_) external override onlyOwnerfunction updateTimelock(TimelockController) external overridefunction propose(
address[] memory targets_,
uint256[] memory values_,
bytes[] memory calldatas_,
string memory description_
)
public
override (Governor, IGovernor)
returns (uint256)function clock() public view override (Governor, GovernorVotes, IERC6372) returns (uint48)function state(uint256 proposalId_) public view override(Governor, GovernorTimelockControl, IGovernor) returns (ProposalState)function quorum(uint256 timepoint_) public view override (Governor, GovernorVotesQuorumFraction, IGovernor) returns (uint256)function CLOCK_MODE() public pure override (Governor, GovernorVotes, IERC6372) returns (string memory)function _checkSelectors(
address proposalCreator_,
address[] memory targets_,
bytes[] memory calldatas_
)
private
viewGovernorVotesQuorumFraction(50) sets an initial quorum fraction of 50%.
GovernorTimelockControl(timelock_) ties this governor to the specified timelock.
Ownable(owner_) sets the contract owner.
Stores CALLDATA_HELPER and s_bridge.
calldatas_s_protectedSelectorsByChainIdAndTarget[m_chainId][m_target].If matched, marks m_isProtected = true.
Otherwise, if targets_[i] != s_bridge, reads the first 4 bytes from calldatas_[i] as the selector and checks s_protectedSelectorsByChainIdAndTarget[block.chainid][targets_[i]].
If m_isProtected == true and proposalCreator_ != owner(), revert with ProtectedFunctionSelectorUsed().










The Locker is a smart contract where holders lock their EYWA tokens, EYWA token safes, EYWA NFTs with EYWA tokens, and project safes for various durations. The purpose of such locking is to obtain project votes - veEYWA voting power. A user’s voting power depends on the duration for which their tokens are locked. The maximum lock period is 3 years (156 weeks), which provides the highest ratio: 1 locked token = 1 vote. More details can be found here.
To start using the CrossCurve application, navigate to the Locker page under the DAO section. Click «Connect wallet», select a suitable wallet from the list, and confirm the connection, ensuring you are on the official page: https://app.crosscurve.fi/locker
On the Locker page, the current CrossCurve DAO statistics are displayed:
Total locked EYWA - the total number of locked EYWA tokens
Total supply veEYWA - the total issued veEYWA tokens
For detailed mechanics on how voting power is calculated when locking EYWA tokens, click Read docs.
To create a new EYWA token lock, click Lock Tokens
The page Create token lock contains the following elements:
Now you have - the number of created locks and the total veEYWA amount in these locks.
Amount to lock - the number of EYWA tokens from your wallet balance for the new lock, increasing the total veEYWA amount.
Select your vested EYWA to receive veEYWA - an option to select vesting safes for the new lock, adding EYWA tokens from vesting safes to increase the total veEYWA amount.
Select your EYWA NFTs and boost voting power
The Create Token Lock application allows you to add EYWA tokens from your wallet, vesting safes, and the EYWA NFT container either separately or simultaneously*.
You can specify the number of EYWA tokens from your wallet balance in the Amount to lock field, select vesting safes in the Select your vested EYWA to receive veEYWA menu, and select EYWA tokens from NFT containers in the Select your EYWA NFTs and boost voting power menu. After selecting the desired amount of EYWA tokens, vesting safes, and EYWA NFT containers, the application calculates the total locked EYWA tokens in the You lock field and the veEYWA voting power based on the selected lock duration in the You’ll get field.
To create a lock with EYWA tokens from your wallet balance, enter the number of locked tokens in the Amount to lock field and select the lock duration using the slider in the Lock time field. The possible lock duration ranges from 0 to 156 weeks.
Example: 156 locked tokens for a week provide 1 vote. More details can be found in the , but the simple explanation is:
1 EYWA, locked for 3 years = 1 veEYWA
1 EYWA, locked for 2 years = 0.66(6) veEYWA
1 EYWA, locked for 1.5 years = 0.5 veEYWA
1 EYWA, locked for 1 year = 0.33(3) veEYWA
The longer you lock your EYWA, the greater your Voting Power and the bigger the boost you can achieve. Voting power is expressed in the number of veEYWA.
After ensuring the number of locked tokens and the lock duration, the amount of voting power in veEYWA tokens obtained will be displayed in the You’ll get field. Below, the current CrossCurve DAO statistics will be displayed:
Total locked EYWA - the total number of locked EYWA tokens in DAO
Total supply veEYWA - the total issuance of veEYWA tokens
Average EYWA NFT boost - the average boost multiplier obtained for locking an EYWA NFT, depending on the rarity of the NFT being locked (more details )
To create a lock, click Create Token lock and sign the transaction in your wallet. If you do not have EYWA tokens in your wallet, use the direct Buy token link for purchase.
After successful on-chain conformation of the transaction, detailed information about the existing locks will be displayed on the page:
To add EYWA tokens from vesting safes to the newly created lock, select safes by clicking Select your vested EYWA to receive veEYWA in the Create Token Lock menu. The possible ranges from 0 to 156 weeks.
In the modal window, you will see a list of all available Vested EYWA safes and information about the total number of safes Total in wallet, as well as the sum of all EYWA tokens in them.
Select a safe (or a group of safes of the same type) to create a lock by clicking the checkbox to the left of the safe. The Locker will display the number of selected safes and EYWA tokens in them in the You selected window. A maximum of 100 safes can be selected per transaction when creating one lock*. To continue, click Lock selected.
Returning to the Create Token Lock menu, the number of selected safes and EYWA tokens in them will be displayed in the Selecting field.
To add Vested EYWA safes to the lock, select the lock duration using the slider in the Lock time field. The possible ranges from 0 to 156 weeks. After selecting the lock duration, the You’ll get field will display the total amount of voting power received in veEYWA tokens. If you need to create a lock only from vesting safes, click Create Token lock and sign the transaction in your wallet.
To add EYWA tokens from EYWA NFT containers to the newly created lock, click Select your EYWA NFTs and boost voting power in the Create Token Lock menu. The possible ranges from 0 to 156 weeks.
In the modal window, you will see a list of all available EYWA NFTs in the connected wallet, sorted by their rarity, along with detailed information:
EYWA tokens - the number of EYWA tokens attached to the NFT container (more details )
Capacity - the capacity of the NFT container (more details )
veEYWA Boosted - NFT boost (more details )
If there are no EYWA NFTs in the connected wallet, use the quick buy link in the Aurora () or Arbitrum ()
Select an NFT* (or a group of NFTs of the same rarity) to create a lock by clicking the checkbox to the left of the NFT. The Locker will display the number of selected NFTs and EYWA tokens in containers in the Selected field. A maximum of 100 NFTs can be selected per transaction when creating one lock. To continue, click Lock EYWA NFTs.
* Attention! In some cases, EYWA NFT may be unavailable for adding to the lock:
If you have detached EYWA tokens from the EYWA NFT container, that EYWA NFT will have a 4-hour freeze period. Only after the timer has expired can you add that NFT to the lock.
If the EYWA NFT container has EYWA tokens without vesting attached, you must them in EYWA NFT Manager (use quick ) so that this NFT becomes available for adding to the lock. After detaching EYWA tokens, this NFT will be frozen for 4 hours (frontrun protection).
Returning to the Create Token Lock menu, the line Selecting will display the number of selected NFTs and the number of EYWA tokens in the containers, and in the line Average EYWA NFT boost, the average boost for vote will be calculated depending on the rarity of the selected NFTs.
To create the EYWA NFTs lock, select the lock duration using the slider in the Lock time field. The possible ranges from 0 to 156 weeks. After selecting the lock duration, the You’ll get field will display the amount of voting power boost obtained (more details ). If you need to create a lock only from EYWA NFTs, click Create Token lock and sign the transaction in your wallet.
If the Amount to Lock field is set to 0 EYWA and no EYWA in vesting is selected, and you have selected an EYWA NFT with no EYWA tokens attached, a message will appear: Unselect NFTs with 0 EYWA or add EYWA tokens. In this case, to create the lock, you must fulfill one of the following conditions:
Unselect the NFT with 0 EYWA tokens in the selection menu Select your EYWA NFTs and boost voting power
Add EYWA tokens from your wallet balance in the Amount to lock, or add EYWA tokens with vesting in the selection menu Select your vested EYWA to receive veEYWA.
During the lock period, you can manage accrued rewards and add EYWA tokens and EYWA NFTs to the lock.
To start working using the CrossCurve application, go to the Locker page in the DAO section. Click «Connect wallet», select the appropriate wallet from the list, and confirm the connection, ensuring you are on the official page:
On the Locker page, detailed information about existing locks will be displayed:
id - D number of EYWA DAO NFT (ID number assigned after creating a new lock through Create lock)
Locked EYWA - the number of EYWA tokens in the EYWA DAO NFT safe
NFTs - the number of EYWA NFTs inside the lock
Unlock time - the next lock expiration date
* There are two states of lock transferability:
The label Available, means that this EYWA DAO NFT (lock) is free for transfer, sale, and unlocking if the lock period has expired.
The snowflake icon means that the transfer is frozen, and this EYWA DAO NFT cannot be moved, sold, or unlocked. Freezing can occur for two reasons:
EYWA DAO NFT is currently or was previously involved in voting during an epoch. In this case, to remove the frozen status, you need to cancel the vote by clicking
The Available status means that the EYWA DAO NFT can be transferred, sold, or unlocked (if the lock period has ended).
The status with the Unfreeze link next to it means that the transfer is frozen - this lock is currently participating in voting for the current or previous epoch. To transfer, you must cancel the vote. To cancel the vote, click Unfreeze and confirm the vote cancellation in the modal window.
To confirm vote cancellation in the current/previous voting rounds, click Reset votes and sign the transaction in your wallet.
After confirming the transaction on-chain, the EYWA DAO NFT will become available for transfer.
The status with the Timer icon means that the EYWA DAO NFT is unavailable for transfer after detaching the EYWA NFT. You must wait 4 hours (front-running protection) before the EYWA DAO NFT can be moved.
Once the timer expires, the transferability status will change to Available.
To add accrued Staking rewards to the lock, click Compound and sign the transaction in your wallet. The EYWA Staking rewards tokens will be added to the lock for which they were received, for the same duration as the existing lock.
To add EYWA tokens to an existing lock and extend it, click Manage.
Information about the selected lock will be displayed:
Unlocking on - the lock expiration date
Already locked - the number of locked EYWA tokens and vesting safes
Owned - voting power in veEYWA tokens
To view detailed information about existing vesting safes, click View
In the Vested EYWA modal window, detailed information about your vesting safes will be displayed:
The round name when the safe was received and the number of identical vesting safes (more details )
All tokens - the number of EYWA tokens in the vesting safe
Unlocked EYWA - the number of EYWA tokens received from the vesting safe
Vesting ends in - the vesting expiration time
2.1 To add EYWA tokens to the lock, enter the amount in the Amount to compound field.
To update the lock duration, select Update time lock and set a new lock duration using the slider.
After entering the amount and selecting the lock duration, the application will display the total number of EYWA tokens ready for locking in the You lock field and the voting power (veEYWA) obtained after the changes in the You’ll get field. To update the lock, click Update Locker and confirm the transaction in your wallet.
2.2 To add EYWA tokens from EYWA NFT containers to the lock and receive a voting power boost, click Select your EYWA NFTs and boost voting power in the Manage Locker menu.
In the modal window, you will see a list of all EYWA NFTs available in your connected wallet, sorted by rarity, along with detailed information. If there are no EYWA NFTs in your connected wallet, use the quick purchase link for Aurora () or Arbitrum ()
Select an NFT (or a group of NFTs of the same rarity) to add to the lock by clicking the checkbox next to the NFT. The Locker will display the number of selected NFTs and EYWA tokens in the containers in the Selected field. A maximum of 100 NFTs can be selected per transaction when adding NFTs to a lock. To continue, click Lock EYWA NFTs
Returning to the Manage Locker menu, the Selecting field will display the number of selected NFTs and EYWA tokens in the containers. To update the lock duration, select Update time lock and set a new lock duration using the slider.
After selecting the lock duration, the application will display the total number of EYWA tokens ready for locking in the You lock field, the voting power (veEYWA) obtained after the changes in the You’ll get field, and the average voting power boost in the Average EYWA NFT boost. To update the lock, click Update Locker and confirm the transaction in your wallet.
The EYWA NFT in locks window displays detailed information about EYWA NFTs locked in the DAO:
Transferable - lock transferability status (more details here)
Locked EYWA NFTs - the number of EYWA NFTs locked in the DAO
Unboosted tokens - the number of EYWA tokens that were not counted in the boost calculation due to container capacity limitations.
Average boost - the average boost value obtained for the EYWA NFT lock (more details )
To transfer an NFT from the lock, click Withdraw
In the modal window, you will see a list of EYWA NFTs locked in the DAO, sorted by rarity and detailed information:
Capacity - NFT container capacity (more details here)
veEYWA Boosted - NFT boost (more details here)
If there are no EYWA NFTs in your connected wallet, use the quick purchase link for Aurora () or Arbitrum ()
Select an NFT* (or a group of NFTs of the same rarity) to unlock by clicking the checkbox next to an NFT. A maximum of 100 NFTs can be unlocked per transaction.
To confirm vote cancellation in the current/previous voting rounds, click Reset votes and sign the transaction in your wallet.
After confirming the transaction on-chain, the EYWA NFT will become available for unlocking.
To continue unlocking EYWA NFTs, click Withdraw EYWA NFTs and confirm the transaction in your wallet.
Once the lock period ends, the Unlock button will become available. To unlock the EYWA DAO NFT and manage safes, click Unlock.
To confirm unlocking* click OK and sign the transaction in your wallet.
3.1. If you want to unlock the EYWA DAO NFT that is/was involved in voting, you need to cancel the votes. To cancel the votes, click Unfreeze and confirm the vote cancellation in the modal window.
Alternatively, clicking Unlock will bring up a modal window displaying the lock contents and a prompt to unfreeze the EYWA DAO NFT to access its contents.
To unfreeze the selected EYWA DAO NFT, click Unfreeze to unlock. The You’ll get field will show the number of unlocked EYWA tokens, vesting safes, and NFTs.
To confirm the vote cancellation in the current/previous voting rounds, click Reset votes and sign the transaction in your wallet.
After confirming the transaction on-chain, the EYWA DAO NFT will become available for unlocking.
3.2. If you want to unlock an EYWA DAO NFT that has a timer set after detaching an NFT, you must wait 4 hours (front-running protection) before it can be moved. Click Unlock to initiate the process.
Once the timer expires, the EYWA DAO NFT will become available for transfer.
Lock time - selection of the locking duration.
veEYWA - the voting power amount in veEYWA tokens for the selected lock
Staking APY - the APY yield for locked EYWA tokens (more details on staking APY here)
Transferable - the status of the selected NFT’s transferability*
Staking rewards - the amount of rewards received in EYWA tokens for the past lock period
If an EYWA NFT was detached from an EYWA DAO NFT, a timer will be displayed showing the time remaining until the freeze is lifted, after which the EYWA DAO NFT can be moved. This is one of the front-running protection mechanisms.
Total in lock - the total number of vesting safes in the lock and the total amount if EYWA tokens in them.









































CrossCurve liquidity pools are starting their migration from the Fantom network to the Sonic network (learn more here). In this step-by-step guide, we will explore how to safely and profitably transfer your liquidity.
Please carefully read the entire list of required actions for transferring liquidity before starting the process.
When migrating to Sonic, the architecture of the pools changes—instead of pools with 8 directions, paired pools are now used. Therefore, before transferring liquidity, please decide which paired pools you will transfer your liquidity to and how you will do it:
You can simply withdraw liquidity from a pool with 8 tokens and distribute it across 8 corresponding paired pools.
Alternatively, you can divert all liquidity from such a pool to a single paired pool or split it across several.
It’s also important to understand that, unlike the previous architecture, paired pools now include not only the directional token (synthetic) but also a "universal" token (xfrxUSD for USD, xfrxETH for ETH, and scBTC for BTC assets). Thus, transferring liquidity will require both the destination token and the "local universal" token.
There are numerous ways to transfer liquidity, and it’s impossible to describe every scenario, so we’ll outline the key general steps:
Choose the pool to which liquidity will be transferred, for example, xsArbitrum.
Determine how many of each token is needed. In the Arbitrum example, you’ll need 25% frxUSD tokens and 25% scUSD tokens to obtain 50% xfrxUSD and 50% sUSDC_arb (percentages are based on the total liquidity planned for transfer to the xsArbitrum pool).
Obtain the synthetic token corresponding to this direction—in this case, sUSDC_arb.
If you provided liquidity to CrossCurve pools on the Farms tab in the Fantom network, you’ll need to follow these steps to transfer your funds from the Fantom network to the Sonic network:
Unstake your position on the Farms page.
Decide which pools your liquidity will be transferred to:
You can distribute liquidity across 8 directions.
You can choose one or several directions.
Decide which method you’ll use to transfer liquidity:
In Easy Mode, directly swap LP tokens from the pool for the required tokens.
Note: This may result in losses due to conversion and slippage. For low liquidity pools and large amounts, losses can be significant.
Examples of swap directions in Easy Mode:
xSTABLE → sUSDT_eth
xSTABLE3 → sUSDC_arb
xSTABLE2 → sUSDC_ba
This method is more labor-intensive but allows for the most cost-effective swaps and is better suited for large liquidity amounts.
Examples of swap directions in Balanced Mode:
s3CRV_e → sUSDT_eth
s2CRV_ar → sUSDC_arb
s4pool_b → sUSDC_ba
Swap your FTM for S (or obtain S) to pay for gas (gwei).
Obtain the universal token for paired pools:
For USD pools, obtain the LP token xfrxUSD.
For ETH pools, obtain the LP token xfrxETH.
For BTC pools, obtain the scBTC token.
Obtain a synthetic token corresponding to the desired direction (e.g., sUSDT_eth, sUSDC_arb, sUSDC_ba, etc.)
Deposit liquidity into the pools:
To obtain xfrxUSD, deposit frxUSD and scUSD into the pool.
To obtain xfrxETH, deposit frxETH and scETH into the pool.
Lock liquidity in the new pools on the Sonic network to earn profits.
Important Note: Rewards distribution in CrossCurve pools on the Fantom network will end at the conclusion of the current epoch. Voting for these pools and reward distribution to DAO participants in these pools will be paused. Starting from the next epoch, voting for reward allocation in the new pools on the Sonic network will begin.
Each paired pool in the Sonic hub-chain consists of two tokens:
A universal token—an asset from Sonic, common for all pools of the same type (xfrxUSD for USD assets, xfrxETH for ETH, and scBTC for BTC).
A synthetic derivative, backed by the original asset locked in the Consensus Bridge. This can be either a single asset or LP tokens from Curve.
Universal tokens come in three types:
For USD pools: LP token xfrxUSD.
For ETH pools: LP token xfrxETH.
For BTC pools: scBTC token.
To obtain xfrxUSD, follow these three steps:
Obtain frxUSD on Sonic.
Obtain scUSD on Sonic.
Deposit frxUSD and scUSD into the CrossCurve frxUSD pool to receive xfrxUSD.
You can obtain frxUSD and scUSD in various ways; below are a few methods.
frxUSD tokens on the Fraxtal network can be swapped from any available asset in the app.
Then, bridge them to the Sonic network on .
In the app, you can transfer any available asset to the Ethereum network, receiving USDT, USDC, or DAI.
Then, scUSD tokens can be swapped in the app by depositing the available assets as collateral.
Choose your preferred app from the list of bridges in the section under Apps in the Bridge category.
Swaps are also available on the aggregator for any available assets.
To obtain the LP token xfrxUSD, you need to provide liquidity in the pool:.
Go to the pool page and connect your wallet.
Enter the desired deposit amount on the Deposit tab. To avoid losses due to slippage, it’s recommended to deposit funds in a balanced manner by clicking Add all coins in a balanced proportion (learn more ).
In the first transaction, confirm the spending of funds by clicking Approve Spending and signing the transaction in your wallet.
In the second transaction, deposit the funds by clicking Deposit and signing the transaction in your wallet.
After the transaction is successfully confirmed on-chain, your wallet will display the amount of received xfrxUSD LP tokens.
If your wallet doesn’t support automatic token addition, add it manually as a custom token with the contract address on the Sonic network.
To obtain xfrxETH, follow these three steps:
Obtain frxETH on Sonic.
Obtain scETH on Sonic.
Deposit frxETH and scETH into the CrossCurve frxETH pool to receive xfrxETH.
You can obtain frxETH and scETH in various ways; below are a few methods.
wfrxETH tokens on the Fraxtal network can be swapped from any available asset in the app.
Then, bridge them to the Sonic network on .
In the app, you can transfer any available asset to the Ethereum network, receiving WETH or ETH.
Then, scETH tokens can be swapped in the app by depositing the available assets as collateral.
Choose your preferred app from the list of bridges in the section under Apps in the Bridge category.
Obtaining scETH or frxETH Using the Jumper.exchange aggregator
Swaps are also available on the aggregator for any available assets.
To obtain the LP token xfrxETH, you need to provide liquidity in the pool:.
Go to the pool page and connect your wallet.
Enter the desired deposit amount on the Deposit tab. To avoid losses due to slippage, it’s recommended to deposit funds in a balanced manner by clicking Add all coins in a balanced proportion (learn more ).
In the first transaction, confirm the spending of funds by clicking Approve Spending and signing the transaction in your wallet.
In the second transaction, deposit the funds by clicking Deposit and signing the transaction in your wallet.
After the transaction is successfully confirmed on-chain, your wallet will display the amount of received xfrxETH LP tokens.
If your wallet doesn’t support automatic token addition, add it manually as a custom token with the contract address on the Sonic network.
You can obtain scBTC using the official Rings issuer app. Alternatively, you can use third-party services listed below.
In the app, you can transfer any available asset to the Ethereum network, receiving WBTC.
Then, scBTC tokens can be swapped in the app by depositing WBTC on the Ethereum network as collateral.
Choose your preferred app from the list of bridges in the section under Apps in the Bridge category.
Obtaining scBTC using the Jumper.exchange aggregator
Swaps are also available on the aggregator for any available assets.
Each paired pool on the Sonic hub-chain consists of two tokens:
A universal token – an asset from Sonic, uniform across all pools of the same type (e.g., xfrxUSD for USD assets, xfrxETH for ETH, and scBTC for BTC).
A synthetic derivative, backed by the original asset locked in the Consensus Bridge. These can be either single assets or LP tokens from Curve.
sUSDC_arb tokens on the Sonic network can be swapped from any available asset in the xsArbitrum pool via the app.
Navigate to the Liquidity tab in the Yield section. Select the Balanced mode and click Next.
Enter the desired amount to swap, approve the spending by clicking Approve, and sign the transaction in your wallet.
Click Swap to execute the exchange and confirm the transaction in your wallet.
If you know the swap direction, you can also perform the exchange in the tab using any available asset.
Note: Some directions may experience high slippage!
To provide liquidity to Sonic pools:
Select the pool where you want to transfer liquidity, e.g., xsArbitrum.
Determine the required token amounts.
For the Arbitrum example, you need 25% frxUSD and 25% scUSD to obtain 50% xfrxUSD and 50% sUSDC_arb (percentages are based on the total liquidity you plan to transfer to the xsArbitrum pool).
Obtain the synthetic token for this direction, in this case, .
For USD pools, acquire tokens. For example, deposit an equal amount of and into the pool.
Deposit the universal token and the directional (synthetic) token into the paired pool.
In our example, deposit xfrxUSD and sUSDC_arb into the CrossCurve Stable ARB pool.
Navigate to the pool page: and connect your wallet.
Enter the desired deposit amount in the Deposit tab. To avoid losses due to slippage, it’s recommended to deposit using the balanced method by clicking Add all coins in a balanced proportion (more details ).
In the first transaction, approve the spending by clicking Approve Spending and sign the transaction in your wallet.
In the second transaction, deposit the funds by clicking Deposit and sign the transaction in your wallet.
After the transaction is confirmed on-chain, the amount of received xsArbitrum LP tokens will appear in your wallet.
If your wallet doesn’t automatically add the token, manually add it as a custom token using the contract address on the Sonic network.
LP xsArbitrum tokens on the Sonic network can be swapped from any available asset in the xsArbitrum pool via the app.
Go to the Liquidity tab in the Yield section. Select the Easy mode and click Next.
Choose the available asset for the swap.
Enter the desired amount to swap, approve the spending by clicking Approve, and sign the transaction in your wallet.
Click Swap to execute the exchange and confirm the transaction in your wallet.
To provide liquidity to CrossCurve pools navigate to the Farms page in the Yield section: and connect your wallet.
In the xsArbitrum pool tab, click Stake LP and get rewards.
Enter the deposit amount, approve the spending by clicking Approve, and sign the transaction in your wallet.
After successful confirmation, deposit the funds by clicking Stake and sign the transaction in your wallet.
The deposited amount will appear in the Staked field.
You can view the current vAPR and accrued rewards in the selected pool by clicking on the APY icon.
CrossCurve MetaLayer introduces a fundamentally new approach—liquidity isolation, where each pool contains liquidity for only one direction:
V2 Each paired pool in the hub-chain consists of two tokens:
A universal token—an asset from Sonic, common for all pools of the same type (xfrxUSD for USD assets, xfrxETH for ETH, and scBTC for BTC).
A synthetic derivative, backed by the original asset locked in the Consensus Bridge. This can be either a single asset or LP tokens from Curve.
As a result, all xSTABLE pools will transform into 20+ paired pools. When transferring liquidity, it won’t be possible to do a one-to-one transfer, as paired pools require an additional "universal" pool token.
For USD and ETH pools, you’ll need to obtain xfrxUSD or xfrxETH tokens, respectively. To do this, in Sonic, you need to acquire frxUSD, scUSD, frxETH, and scETH accordingly. For example, you’ll need equal amounts of frxUSD and scUSD to deposit into the CrossCurve frxUSD pool.
Deposit the universal token and the destination token (synthetic) into the paired pool. In our example, you’ll need to deposit xfrxUSD and sUSDC_arb into the CrossCurve Stable ARB pool.
In Balanced Mode, withdraw 8 synthetic tokens from the LP token and swap them directly.
After successfully claiming rewards from the pool, click Unstake to withdraw LP tokens from staking.
In the modal window, to select the maximum number of LP tokens to withdraw, click MAX next to the token balance in your wallet, then click Unstake to withdraw your liquidity from the pool and receive LP tokens on the Fantom network.
Sign the transaction in your wallet.
Easy Mode via CrossCurve
To quickly withdraw liquidity using Easy Mode, go to the Liquidity page under the Yield tab.
In the pool list, under Choose pool, select the pool where you provided liquidity and have LP tokens.
Select the withdrawal mode Withdraw, operation type Easy Mode, and click Next to proceed.
Choose the asset you want to swap your LP token for by opening the selection list.
Enter the amount of LP tokens to swap or click MAX to select the entire balance from your wallet. Click Approve and confirm the LP token spending operation in your wallet.
After confirming the spending operation, click Swap to perform the exchange and sign the transaction in your wallet.
Wait for the transaction to be processed on-chain.
Balanced Mode via Curve
To withdraw liquidity in Balanced Mode, go to the page of the pool you’re interested in on the Curve app using the quick link.
If you haven’t performed an unstake in the CrossCurve app, go to the Withdrawal/Claim menu under the Unstake tab. Enter the number of LP tokens to unstake, click Unstake, and sign the transaction in your wallet.
After the transaction is successfully confirmed on-chain, you’ll see a notification: Unstake Complete.
Claim the rewards on the Claim Rewards tab by clicking Claim and signing the transaction in your wallet.
To withdraw liquidity, go to the Withdraw tab, enter the number of LP tokens, select Balanced mode, and click Withdraw. Sign the transaction in your wallet.
After the transaction is successfully confirmed on-chain, you’ll see a notification: Withdraw Complete.
s_WBTC_network, where WBTC represents BTC backing, and chain is the network where the asset is used.
xb_chain, where xb is a volatile pool, and chain is the network where the asset is used.
DelegationManagerV1 This is an upgradeable contract that allows you to delegate your locks to another account. This contract is integrated with EmissionManager, EscrowManager, EscrowVoteManager, LockHolderFactory, RebaseRewardsDistributor, DelegationConditionValidator. It allows the lock owner to delegate or automate actions such as voting and collecting rebase rewards and incentive rewards.
Key Roles and Features:
Access Control: Restricts setAssuranceLockParameters and setMinLockVeEywa calls to the owner of contract(owner()).
Upgradeable via UUPS: Uses UUPSUpgradeable and OwnableUpgradeable patterns, restricting contract upgrades to the owner.
UUPSUpgradeable (OpenZeppelin): Provides upgrade functionality under the UUPS proxy pattern, restricted to the contract owner.
OwnableUpgradeable (OpenZeppelin): Manages ownership, allowing only the owner to modify critical parameters and authorize upgrades.
IDelegationManagerV1:
Defines core methods (e.g., setDelegationParameters, delegate, vote) and events for this contract.
Additional External References:
SafeERC20, IERC20 (OpenZeppelin): Handles secure ERC20 operations for distributing and approving token transfers.
IRebaseRewardsDistributorV2: Distributes rebase rewards and triggers relevant accounting updates.
IDelegationConditionValidatorV1: Logic to test additional conditions for delegation
ILockHolderFactoryV1: Deployment of new LockHolder contracts
EPOCH_DURATION: Duration of each emission/gauge epoch (1 week).
PRECISION: The divisior for percentage math.
s_eywa (IERC20)
ERC20 token interface for the EYWA token.
s_collection (ICollection)
ICollection Interface for the NFT collection contract.
s_emissionManager (IEmissionManagerV1)
IEmissionManagerV1 interface for the EmissionManagerV1 contract.
Description: Disables contract initializers to prevent re-initialization in a UUPS proxy context.
initialize(...)Description: Configures ownership, references, and initial state:
Sets s_minLockEywa to 500 000 * 1e18 initially.
Sets s_minLockVeEywa to 1 000 * 1e18 initially.
Sets s_minLockDuration to 52 weeks initially.
Parameters:
owner_: The address of the contract owner.
eywa_: ERC20 token interface for the EYWA token.
collection_: ICollection Interface for the NFT collection contract.
setAssuranceLockParameters(uint256 minLockEywa_, uint256 minLockDuration_)Description: Setting parameters for the delegate assurance lock
Parameters:
Checks:
Only the owner of the contract can call this function.
setMinLockVeEywa(uint256 minLockVeEywa_)Description: Setting the minimum veEYWA value for delegated locks
Parameters:
minLockVeEywa_: The minimum number of veEYWA that must be in the delegated lock.
Checks:
Only the owner of the contract can call this function.
setDelegationParameters(DelegationParameters memory delegationParameters_)Description:
Setting delegation parameters for the delegate If this is the first time a delegate is setting parameters, its address is added to the delegate array (s_delegaties) delegationParameters_.eywaDeposit and the delegate's current deposit. Delegation parameters can only be changed once the rewards have been received and distributed and rent has been paid for all delegated locks. When one or more parameters are changed: delegationParameters_.maxDelegatedVeEYWA, delegationParameters_.delegationEnd, delegationParameters_.eywaDeposit - the rent per veEYWA unit per epoch is recalculated. Performs a transfer of the required number of EYWA tokens from the delegate's account to his deposit in the contract. This deposit will be used to pay for lock rentals to delegates. The required number is calculated as the difference between
Parameters:
delegationParameters_: Parameters of the delegation.
Checks:
The delegate must pass the correct parameters. Otherwise, WrongDelegationParameters() is thrown.
The delegate assuranceLock lock must comply with the requirements set forth. Otherwise, BadAssuranceLock() is thrown.
All rewards for all delegated locks must be received. Otherwise, RewardsUnclaimed() is thrown.
setDelegationVoteParameters(address[] calldata pools_, uint256[] calldata weights_)Description: Setting the parameters auto-voting for a specific delegate.
Parameters:
pools_: The array of voting pools.
weights_: The array with voice weights for each pool.
Checks:
pools_ and weights_ arrays must not be null and must have the same size. Otherwise, InvalidArrayLengths() is thrown.
setAutoVotePermission(bool permission_)Description: Set the permission for automatic voting using the autoVote function. With this permission, this autoVote function can be called by any account. To perform automatic voting, you must set the parameters with the setDelegationVoteParameters function
Parameters:
permission_: The permission parameter.
boost(uint256 tokenId_, uint256[] calldata collectionTokenIds_)Description: The function proxies the call of the boost function on the EscrowManager contract.
Parameters:
tokenId_: The ID of the token representing the lock.
collectionTokenIds_: An array of token IDs from the collection that will be used to boost the lock.
Checks:
The lock must be self-delegation and the caller must be a delegator. Otherwise, UnauthorizedCaller() is thrown.
Delegation time should not be finalized. Otherwise, DelegateTimeExpired() is thrown.
deboost(uint256 tokenId_, uint256[] calldata collectionTokenIds_)Description: The function proxies the call of the deboost function on the EscrowManager contract. And then performs a transfer of the NFTs withdrawn from the lock to the delegator balance.
Parameters:
tokenId_: The ID of the token representing the lock.
collectionTokenIds_: An array of token IDs from the collection that will be used to boost the lock.
Checks:
The lock must be self-delegation and the caller must be a delegator. Otherwise, UnauthorizedCaller() is thrown.
extend(uint256[] calldata tokenIds_, uint256[] calldata lockDurations_)Description: The function proxies the call of the extend function on the EscrowManager contract.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
collectionTokenIds_: An array of token IDs from the collection that will be used to boost the lock.
Checks:
The tokenIds_ and lockDurations_ arrays must have the equal length. Otherwise, InvalidArrayLengths() is thrown.
For each lock from tokenIds delegatee_ must be a delegator. Otherwise, WrongDelegatee() is thrown.
withdrawDeposit(uint256 amount_)Description:
Function for deposit withdrawal. Performs transfer of amount_ of EYWA tokens from contract balance to msg.sender balance. Decreases by amount_ the value in s_depositByDelegatee on the msg.sender key. A delegate can only withdraw a deposit if the current delegation has been completed and all payments for all delegated locks have been made.
Parameters:
amount_: The amount of EYWA tokens.
Checks:
Checks that the delegate's deposit is not less than amount_. Otherwise, NotEnoughAmount() is thrown.
Fee must be paid for each delegated lock. Otherwise, DelegationUnpaid() is thrown.
claim()Description: The function transfers EYWA, received as a commission for delegated locks, to the balance of the delegator
delegate(address delegatee_, uint256[] calldata tokenIds_)Description:
This function performs a number of necessary checks, after which the internal function _delegate() is called, in which delegation takes place.
Parameters:
delegatee_: The delegate's address.
tokenIds_: An array of IDs of the token representing the lock.
Checks:
If it is not a self-delegation, it is checked that delegatee_ has set the delegation parameters. Otherwise, DelegateeNotExist() is thrown.
If it is not self-delegation, it is verified that the condition of the assurance lock is as specified. Otherwise, BadAssuranceLock() is thrown.
If it is not a self-delegation, iit is checked that the maximum number of veEYWA specified in the delegation parameters will not be exceeded. Otherwise, MaxDelegatedVeEywaExceeded()
Events:
Emits Delegate(delegator, delegatee, tokenIds).
paymentAndExtendDelegations(uint256[] calldata tokenIds_)Description: The function transfers lock commissions from the delegatee's deposit to the delegator's deposit, for all epochs since the last time the commission was received, and renews locks
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
claimIncentives(uint256[] calldata tokenIds_)Description: The function proxies the call of the claimIncentives function on the LockHoldeV1 contract. After collecting and distributing the bounty, notes that the bounty for the specified locks is received in this epoch.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
revokeDelegations(uint256[] calldata tokenIds_)Description: Function to revoke the delegation. Sets the start of the next epoch to the time the delegation ends. After the start of the next epoch, these delegated locks cannot be voted on.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
Checks:
For each lock from tokenIds_, it is checked that the function is called by a delegator or delegate. Otherwise, UnauthorizedCaller() is thrown.
For each lock from tokenIds_, it is checked that its delegation time has not yet expired. Otherwise, DelegateTimeExpired() is thrown.
recallDelegations(uint256[] calldata tokenIds_)Description: Delegation Completion Function. In the normal situation, this function is called in the next epoch, after the revokeDelegations function has been called. For self-delegated locks, this function can be called at any time, without first calling the revokeDelegations function. If the delegation time specified in the delegation parameters has expired, you can call this function, without first calling the revokeDelegations function. After partitioning a lock, reduces by its veEYWA value the amount of veEYWA delegated to the delegate.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
Checks:
You can't recall assurance lock. Otherwise, DelegationWithdrawalForbidden() is thrown.
For each lock from tokenIds_, it is checked that the function is called by a delegator or delegate. Otherwise, UnauthorizedCaller() is thrown.
All rewards for all delegated locks must be received. Otherwise, RewardsUnclaimed() is thrown.
Events:
Emits RecallDelegations(tokenIds_).
function vote(uint256[] calldata tokenIds_, address[][] calldata pools_, uint256[][] calldata weights_)Description: The function proxies the call of the extend function on the EscrowVoteManager contract.
For each lock from tokenIds_ the necessary checks are performed in the internal function _checkDelegation, which will be described in detail below
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
pools_: An array of voting pools.
weights_: An array with voice weights for each pool.
autoVote(address delegatee_, uint256[] calldata tokenIds_)Description: The function proxies the call of the extend function on the EscrowVoteManager contract.
The delegate must set permission for auto-voting in the setAutoVotePermission function and set the voting parameters in the setDelegationVoteParameters function. Then any account can perform voting by delegated locks of this delegate using the set parameters.
For each lock from tokenIds_ the necessary checks are performed in the internal function _checkDelegation, which will be described in detail below
Parameters:
delegatee_: An array of IDs of the token representing the lock.
tokenIds_: An array of IDs of the token representing the lock.
Checks:
The delegatee_ must set the authorization for auto-voting. Otherwise, NotSetAutoVote() is thrown.
The delegatee_ must set the parameters for auto-voting. Otherwise, NotSetAutoVoteParameters() is thrown.
For each lock from tokenIds
reset(uint256[] calldata tokenIds_)Description: The function proxies the call of the reset function on the EscrowVoteManager contract.
For each lock from tokenIds_ the necessary checks are performed in the internal function _checkDelegation, which will be described in detail below.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
poke(uint256[] calldata tokenIds_)Description: The function proxies the call of the poke function on the EscrowVoteManager contract.
For each lock from tokenIds_ the necessary checks are performed in the internal function _checkDelegation, which will be described in detail below.
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
isAvailableDelegate(address delegator_, address delegatee_, uint256[] calldata tokenIds_)Description:
The function checks all current delegation parameters accepts determines whether delegation from delegator_ to delegatee_ of tokenIds_ locks is possible. Returns true/false - delegation is or is not possible for the given values
Parameters:
delegator_: The delegator's address.
delegatee_: The delegate's address.
tokenIds_: An array of IDs of the token representing the lock.
getDelegationsParameters()Description: The function returns an array of parameters of all delegates
getDelegationsVoteParametersByDelegate(address delegatee_)Description:
The function returns the auto-voting parameters for a specific delegatee_
Parameters:
delegatee_: The delegate's address.
getDelegationsInfoByTokenIds(uint256[] calldata tokenIds_)Description: The function returns an array with delegation information for an array of delegations
Parameters:
tokenIds_: An array of IDs of the token representing the lock.
getDelegationInfoAndParametersByTokenId(uint256 tokenId_)Description:
The function returns delegation information delegationInfo_ and delegation parameters delegationParameters_ for a specific delegated lock by its tokenId_
Parameters:
tokenId_: The ID of the token representing the lock.
getLockIdsByDelegator(address delegator_)Description:
The function returns an array of id's of all locks delegated by the delegator_
Parameters:
delegator_: The delegator's address.
getLockIdsByDelegatee(address delegatee_)Description:
The function returns an array of id's of all locks delegated to the delegatee_
Parameters:
delegatee_: The delegate's address.
getAssuranceLockStatus(uint256 tokenId_, address delegatee_)Description:
The function checks and returns true/false the status of tokenId_ as a Assurance lock for the delegatee_
Parameters:
tokenId_: The ID of the token representing the lock.
delegatee_: The delegate's address.
_delegate(IEscrowManagerExtended escrowManager_, DelegationParameters memory delegationParameters_, uint256[] calldata tokenIds_, address delegatee_)Description:
The delegation function performs the necessary checks and then performs a lock transfer to the LockHolder contract, and the entire veEYWA of the lock is transferred to the delegate_ account. If this sender delegates locks to this delegate_ for the first time, a new LockHolder contract is deployed for them. The necessary data structures are also created to store information about the delegated lock. If a sender address or null address is specified as delegate_, self-delegation occurs.
Parameters:
escrowManager_: The IEscrowManagerExtended interface for the EscrowManager contract.
delegationParameters_: Parameters of the delegation.
tokenIds_: The array of IDs of the token representing the lock.
Checks
If it is not a self-delegation, checked that the veEYWA value of all lots specified in tokenIds_ is not less than the s_minLockVeEywa value set in the contract minVeEYWA set in delegations parameters. Otherwise, WrongVeEywaAmount() is thrown.
If it is not self-delegation, checks that the time to unlock the lock is not lower than the minimum time set by the delegatee_. Otherwise, LittleTimeToUnlock() is thrown.
_recallDelegation(address delegator_, address delegatee_, uint256 tokenId_)Description: Delegation recall function
First, a check is made to see if the vote was made by this tokenId_, and if so, the reset function is called on the LockHolder contract to reset the vote. Otherwise it will be impossible to perform a lock transfer.
The data structures are then overwritten and the data of the revocable delegation is deleted.
At the end, a transfer of the voiting power and lock token to the delegator address is made
Checks:
For tokenId_, it is checked that there exists a LockHolder contract corresponding to the delegate-delegate pair. Otherwise, LockHolderNotExist() is thrown.
Parameters:
delegator_: The delegator's address.
delegatee_: The delegate's address.
tokenId_ The ID of the token representing the lock.
_getVotes(IEscrowManagerExtended escrowManager_, uint256[] calldata tokenIds_)Description:
Returns the sum of veEYWA from an array of locks tokenIds_
Parameters:
tokenIds_: The array of IDs of the token representing the lock.
_getLastEpochOfDelegation(uint256 timeExpiry_, uint256 delegationEnd_)Description: The function returns the completion time of the delegation
Parameters:
timeExpiry_: The expiry timestamp to verify.
delegationEnd_: The epoch in which the delegation will be completed.
_getPaidEpoch(uint256 timeExpiry_, uint256 delegationEnd_, uint256 currentEpochStart_)Description: The function returns the start time of the last paid epoch
Parameters:
timeExpiry_: The expiry timestamp to verify.
delegationEnd_: The epoch in which the delegation will be completed.
currentEpochStart_: The start time of the current epoch.
_checkDelegationPaid(bool isSelfDelegation_, uint256 lastPaidEpoch_, uint256 paidEpoch_)Description: The function checks whether the delegation has been paid in the current epoch. Returned with DelegationUnpaid if the delegation is not paid in the current epoch.
Parameters:
isSelfDelegation_: Indicates whether the delegation is self-delegated.
lastPaidEpoch_: An epoch when the last fee payment was made.
paidEpoch_: An epoch that must be paid for.
Checks
Unless it is self-delegation, the last epoch paid should not be less than the epoch to be paid. Otherwise, DelegationUnpaid() is thrown.
_checkRewardsClaimed(uint256 tokenId_, uint256 currentEpochStart_, address lockHolder_)Description: The function checks to see if available awards have been received. Returned with RewardsUnclaimed if no awards have been received.
Parameters:
tokenId_: Indicates whether the delegation is self-delegated.
currentEpochStart_: The current epoch start.
lockHolder_: The lock holder contract address.
Checks
Unless it is self-delegation, the last epoch paid should not be less than the epoch to be paid. Otherwise, DelegationUnpaid() is thrown.
_checkCaller(address caller_)Description: Internal function to check the caller.
Parameters:
caller_: The expected caller's address.
Checks:
msg.sender must be equal to caller_. Otherwise, UnauthorizedCaller() is thrown.
_checkDelegatorOrDelegatee(address delegator_, address delegatee_)Description: Internal function to verify that the function caller is a delegate or delegator.
Parameters:
delegator_: The delegator's address.
delegatee_: The delegate's address.
Checks:
msg.sender must be equal to delegator_ or delegatee_. Otherwise, UnauthorizedCaller() is thrown.
_checkTimeExpiry(uint256 timeExpiry_)Description: Internal function to check that the delegation time has not expired. If the delegation has been revoked and timeExpiry is not equal to 0, the end time of the delegation must be less than the current time
Parameters:
timeExpiry_: The end time of delegation.
Checks:
block.timestamp must be not equal 0 and greater than timeExpiry_. Otherwise, DelegateTimeExpired() is thrown
_checkLockHolder(address delegator_, address delegatee_)Description: Internal Function to check the LockHolder contract address for a pair of delegator and delegate. Returns the LockHolder contract's address.
Parameters:
delegator_: The delegator's address.
delegatee_: The delegate's address.
Checks:
a LockHolder contract must be deployed for the delegator_ and delegatee_ pair. Otherwise, LockHolderNotExist() is thrown
_checkAssuranceLock(uint256 assuranceLock_, address delegatee_)Description: Internal function to check the assurance lock. Verification that the lock is a self-made lock, or its assurance lock meets the specified requirements
Parameters:
assuranceLock_: The token ID used as the assurance lock.
delegatee_: The delegatee assurance lock.
Checks:
If the conditions are not met for assuarnce lock. Otherwise, BadAssuranceLock() is thrown
_checkDelegation(DelegationInfo memory delegationInfo_, address caller_, uint256 currentEpochStart_)Description: Internal function for check the delegation status. Check caller, time expiry, delegation fee payment. A number of internal functions are called for the checks, which will be described below
Parameters:
delegationInfo_: The delegation information associated with the token.
caller_: The expected caller's address.
currentEpochStart_: The current epoch start.
Checks:
The start time of the current epoch must be less than the end time of the delegation. Otherwise, DelegationEnded() is thrown.
_checkForSelfDelegation(uint256 tokenId_)Description: Internal function for checking self-delegation. Returns the LockHolder contract's address.
Parameters:
tokenId_: The ID of the token representing the lock.
Checks:
When self-delegating for tokenId_, the delegator must be equal to the delegate and both of these values must be equal to msg.sender. Otherwise, UnauthorizedCaller() is thrown
_currentEpochStart()Description: The function returns the start timestamp of the current epoch
_nextEpochStart()Description: The function returns the start timestamp of the next epoch
_getTimeToUnlock(uint256 tokenId_)Description: The function returns the time until the lock is unlocked
Parameters:
tokenId_: The ID of the token representing the lock.
_checkDelegateeExist(address delegatee_)Description: Internal function to check if the delegate has set the delegation parameters
Parameters:
delegatee_: The delegate's address.
Checks:
delegatee_ must have delegation parameters set. Otherwise, DelegateeNotExist() is thrown.
Delegate(address indexed delegator, address indexed delegatee, uint256[] tokenIds)
The event is emitted when the delegation is successful.
RecallDelegations(uint256[] tokenIds)
The event is emitted when the recall delegation is successful.
WrongDelegationParameters()
Thrown if the delegate tries to set the wrong delegation parameters.
BadAssuranceLock()
Thrown if the assurance lock is not compliant.
DelegateeNotExist()
Thrown if the delegate has not set the delegation parameters.
DelegationManagerV1 contract allows the castle owner not to track voting and reward collection, and not to spend ether on transaction fees. The delegate, on the other hand, can earn by taking a percentage of the rewards, sharing them with the castle owner. Alternatively, the castle owner can delegate to himself, which would simply automate the execution of voting and collection of rebase rewards and incentive rewards.
IEscrowManagerExtended: Holds locked token data and checks voting power and freeze logic.
IEscrowVoteManagerV1: Receives gauge emission amounts and coordinates gauge reward distribution.
IEmissionManagerV1: Informs about epoch starts and ensures updated weekly distributions.
ILockHolderV1: Logic for proxied calls to EscrowManager, EscrowVoteManager and IncentiveRewardsDistributor contract functions
ICollection: Components in the ecosystem for NFT.
s_escrowManager (IEscrowManagerExtended)
IEscrowManager interface for the EscrowManager contract.
s_escrowVoteManager (IEscrowVoteManagerV1)
IEscrowVoteManagerV1 interface for the EscrowVoteManager contract.
s_lockHolderFactory (ILockHolderFactoryV1)
ILockHolderFactoryV1 interface for the LockHolderFactoryV1 contract.
s_rebaseRewardsDistributor (IRebaseRewardsDistributorV2)
IRebaseRewardsDistributorV2 interface for the RebaseRewardsDistributorV2 contract.
s_delegationConditionValidator (IDelegationConditionValidatorV1)
IDelegationConditionValidatorV1 interface for the DelegationConditionValidator contract.
s_minLockEywa (uint256)
The min EYWA amount in delegatee's lock.
s_minLockVeEywa (uint256)
The min veEYWA amount in delegatee's lock.
s_minLockDuration (uint256)
The min duration for delegatee's lock in seconds.
s_delegaties (address[])
Array with addresses of all delegates.
s_depositedByDelegatee (mapping(address => uint256))
Mapping from delegatee to its EYWA deposit information.
s_feeByDelegator (mapping(address => uint256))
Mapping from delegator to its EYWA fee information.
s_autoVoteByDelegatee (mapping(address => bool))
Mapping from delegatee to its permission for automatic execution of the autoVote() function.
s_delegationParametersByDelegatee (mapping(address => DelegationParameters))
Mapping from delegatee to its delegation parameters.
s_delegationInfoByTokenId (mapping(address => DelegationInfo))
Mapping from token ID to its delegation information.
s_lastClaimedIncentiveTimeByLockHolder (mapping(address => uint256))
Mapping from LockHolder contract address to its last time claimed incentive.
s_lastClaimedCommissionTimeByLockHolder (mapping(address => uint256))
Mapping from LockHolder contract address to its last time claimed commission.
s_lockHolders (mapping(address => mapping(address => address)))
Nested mapping from delegator and delegatee to their LockHolder contract address.
_s_locksByDelegator (mapping(address => uint256))
Mapping from delegator to its amount of delegated locks.
_s_locksByDelegatee (mapping(address => uint256))
Mapping from delegatee to its amount of delegated locks.
_s_delegationVoteParametersByDelegatee (mapping(address => DelegationVoteParameters))
Mapping from delegatee to its delegation vote parameters.
_s_delegationIndexesInfoByTokenId (mapping(address => DelegationIndexesInfo))
Mapping from token ID to its delegation indexes info.
_s_lockIdByDelegatorAndIndex (address => mapping(uint256 => uint256))
Nested mapping from delegator and index to its delegated lock ID.
_s_lockIdByDelegateeAndIndex (address => mapping(uint256 => uint256))
Nested mapping from delegatee and index to its delegated lock ID.
_s_feeByDelegateeAndEpoch (mapping(address => mapping(uint256 => uint256)))
Nested mapping of delegatee address and an epoch start to a fee.
emissionManager_: IEmissionManagerV1 interface for the EmissionManagerV1 contract.escrowManager_: The IEscrowManagerExtended interface for the EscrowManager contract.
escrowVoteManager_: The IEscrowVoteManagerV1 interface for the EscrowVoteManager contract.
lockHolderFactory_: ILockHolderFactoryV1 interface for the LockHolderFactoryV1 contract.
rebaseRewardsDistributor_: IRebaseRewardsDistributorV2 interface for the RebaseRewardsDistributorV2 contract.
delegationConditionValidator_: IDelegationConditionValidatorV1 interface for the DelegationConditionValidator contract.
Must be paid rent for all delegated tokens. Otherwise, DelegationUnpaid() is thrown.
The value of delegationParameters_.maxDelegatedVeEYWA must not be less than the current total veEYWA value for all locks delegated to this delegate. Otherwise, MaxDelegatedVeEywaExceeded() is thrown.
For each lock from tokenIds_, it is checked that its delegation time has not yet expired. Otherwise, DelegateTimeExpired() is thrown.
The maximum veEYWA value for dlegation should not be exceeded after extend of the locks. Otherwise, MaxDelegatedVeEywaExceeded() is thrown.
For each lock from tokenIds_, it is checked that there exists a LockHolder contract corresponding to the delegate-delegate pair. Otherwise, LockHolderNotExist() is thrown.
If it is not a self-delegation, additional delegation conditions are checked in the validateDelegations function on the DelegationConditionValidator contract. Otherwise, UnvalidatedDelegation() is thrown.
Must be paid rent for all delegated tokens. Otherwise, DelegationUnpaid() is thrown.
The delegation's time must be finalized. Otherwise, DelegationWithdrawalForbidden() is thrown.
delegatee_WrongDelegatee()delegatee_: The delegate's address.InvalidArrayLengths()
Thrown if the array has an invalid length.
UnauthorizedCaller()
Thrown when the caller is not authorized to perform the action.
DelegateTimeExpired()
Thrown when attempting to perform an action with a delegation with expired time.
DelegationEnded()
Thrown when the delegation is complete.
WrongLockDuration()
Thrown when attempting to set a new lock auto-extend time lower than the minimum allowed by the delegation parameters.
LockHolderNotExist()
Thrown if there is no LockHolder for the current delegate and delegate pair.
NotEnoughAmount()
Thrown when there is an insufficient deposit or fee for the requested operation.
DelegationNotEnded()
Thrown when the delegation is not ended.
MaxDelegatedVeEywaExceeded()
Thrown when the maximum number of delegated veEYWA has been exceeded.
UnvalidatedDelegation()
Thrown when validation failed on the DelegationConditionValidator contract.
WrongVeEywaAmount()
Thrown when the voting power of the delegated lock is less than s_minLockVeEywa.
LittleTimeToUnlock()
Thrown when attempting to delegate a lock that has less time to unlock than the minimum time set by the delegate.
NotSetAutoVote()
Thrown when attempting to perform auto-voting if no permission is set.
NotSetAutoVoteParameters()
Thrown when attempting to perform auto-voting if no parameters are set for it.
WrongDelegatee()
Thrown when attempting to perform an auto-vote if the lock is not delegated to the specified delegate.
DelegationWithdrawalForbidden()
Thrown when the delegation time has not yet expired, preventing recall.
RewardsUnclaimed()
Thrown when the delegation time has not yet expired, preventing recall.
DelegationUnpaid()
Thrown when no awards have been received.
uint256 private constant EPOCH_DURATION = 1 weeks;
uint256 private constant PRECISION = 100_000;constructor() {
_disableInitializers();
}function initialize(
address owner_,
IERC20 eywa_,
ICollection collection_,
IEmissionManagerV1 emissionManager_,
IEscrowManagerExtended escrowManager_,
IEscrowVoteManagerV1 escrowVoteManager_,
ILockHolderFactoryV1 lockHolderFactory_,
IRebaseRewardsDistributorV2 rebaseRewardsDistributor_,
IDelegationConditionValidatorV1 delegationConditionValidator_
) external initializer;function setAssuranceLockParameters(
uint256 minLockEywa_,
uint256 minLockDuration_
) external onlyOwner;- `minLockEywa_`: The minimum number of EYWA tokens that must be in the assurance lock.
- `minLockDuration_`: The the minimum time before unlocking that a assurance lock should have.function setMinLockVeEywa(uint256 minLockVeEywa_) external onlyOwner;function setDelegationParameters(InputDelegationParameters memory delegationParameters_) external;function setDelegationVoteParameters(
address[] calldata pools_,
uint256[] calldata weights_
) external;function setAutoVotePermission(bool permission_) external;function boost(
uint256 tokenId_,
uint256[] calldata collectionTokenIds_
) external;function deboost(
uint256 tokenId_,
uint256[] calldata collectionTokenIds_
) external;function extend(
uint256[] calldata tokenIds_,
uint256[] calldata lockDurations_
) external;function withdrawDeposit(uint256 amount_) external;function claim() external;function delegate(
address delegatee_,
uint256[] calldata tokenIds_
) external;function paymentAndExtendDelegations(uint256[] calldata tokenIds_) external;function claimIncentives(uint256[] calldata tokenIds_) external;function revokeDelegations(uint256[] calldata tokenIds_) external;function recallDelegations(uint256[] calldata tokenIds_) external;function vote(
uint256[] calldata tokenIds_,
address[][] calldata pools_,
uint256[][] calldata weights_
) external;function autoVote(
address delegatee_,
uint256[] calldata tokenIds_
) external;function reset(uint256[] calldata tokenIds_) external;function poke(uint256[] calldata tokenIds_) external;function isAvailableDelegate(
address delegator_,
address delegatee_,
uint256[] calldata tokenIds_
) external view returns(bool);function getDelegationsParameters() external view returns(OutputDelegationParameters[] memory);function getDelegationsVoteParametersByDelegate(
address delegatee_
) external view returns(address[] memory pools_, uint256[] memory weights_);function getDelegationsInfoByTokenIds(
uint256[] calldata tokenIds_
) external view returns(DelegationInfo[] memory);function getDelegationInfoAndParametersByTokenId(
uint256 tokenId_
)
external
view
returns(DelegationInfo memory delegationInfo_, DelegationParameters memory delegationParameters_);function getLockIdsByDelegator(address delegator_) external view returns(uint256[] memory);function getLockIdsByDelegatee(address delegatee_) external view returns(uint256[] memory);function getAssuranceLockStatus(
uint256 tokenId_,
address delegatee_
) public view returns(bool);function _delegate(
IEscrowManagerExtended escrowManager_,
DelegationParameters memory delegationParameters_,
uint256[] calldata tokenIds_,
address delegatee_
) private;function _recallDelegation(
address delegator_,
address delegatee_,
uint256 tokenId_
) internal;function _getVotes(
IEscrowManagerExtended escrowManager_,
uint256[] calldata tokenIds_
) private view returns(uint256);function _getLastEpochOfDelegation(
uint256 timeExpiry_,
uint256 delegationEnd_
) internal view returns (uint256);function _getLastEpochOfDelegation(
uint256 timeExpiry_,
uint256 delegationEnd_,
uint256 currentEpochStart_
) internal view returns (uint256);function _checkDelegationPaid(
bool isSelfDelegation_,
uint256 lastPaidEpoch_,
uint256 paidEpoch_
) internal view returns (uint256);function _checkRewardsClaimed(
uint256 tokenId_,
uint256 currentEpochStart_,
address lockHolder_
) internal view returns (uint256);_checkCaller(address caller_) internal view;function _checkDelegatorOrDelegatee(
address delegator_,
address delegatee_
) internal view;function _checkTimeExpiry(uint256 timeExpiry_) internal viewfunction _checkLockHolder(
address delegator_,
address delegatee_
) internal view returns(address);function _checkAssuranceLock(
uint256 assuranceLock_,
address delegatee_
) internal view returns(address);function _checkDelegation(
DelegationInfo memory delegationInfo_,
address caller_,
uint256 currentEpochStart_
) internal view returns(address);function _checkForSelfDelegation(uint256 tokenId_) internal view returns(address);function _currentEpochStart() internal view returns (uint256);function _nextEpochStart() internal view returns (uint256);function _getTimeToUnlock(uint256 tokenId_) internal view returns(uint256);function _checkDelegateeExist(address delegatee_) internal view;Performing a cross-chain swap consists of 4 steps:
Routing construction
Estimating cross-chain operations
Forming data for the transaction
Sending the transaction
Request routing for the specified tokens and networks
Copy
From the obtained array of routes, take the first route (which is the most profitable for swapping) and send it for estimation
Copy
Copy
Copy
After initiating the cross-chain swap (sending the transaction), it is necessary to ensure that it reaches the destination network and is executed successfully. Each cross-chain swap involves several transactions and the number of transactions may vary depending on the operation.
For swapping two stablecoins from Network A to Network B, the route can be depicted as:
Chain A -----> Hubchain -----> Chain B
Each transaction is linked with another by a unique identifier, requestId, which represents the cross-chain transition identifier and can be used to track the source status and transaction destinations.
You can get requestId of a transaction using its hash with the Pusher API:
Copy
Copy
In the results, we are interested in the values of destination.status and destination.transactionHash. If destination.transactionHash is empty, this means that the transaction has not yet been executed and the request should be repeated at intervals until the hash appears.
Then there are 3 scenarios:
Both details.inconsistency and destination.emergency are false This scenario is considered the most correct and will occur in most cases. It means the cross-chain operation has been completed and we have the hash of the destination transaction. Now, using this hash, similarly, you can track the status of the next cross-chain transition (if there is one) and continue doing so until all cross-chain transitions are completed.
details.inconsistency is true This means that the destination transaction was successfully completed, but the token swap did not occur due to slippage. An intermediate result has been returned to your address in this network. The cross-chain operation is considered complete at this point.
The value of destination.emergency is true In this case, the destination network operation could not be executed and your tokens are stuck in the contract. To retrieve them, you need to contact support to request a refund.
POST https://api.crosscurve.fi/api-docs/#/
POST https://api.crosscurve.fi/routing/scan
Request Body
POST https://api.crosscurve.fi/estimate
Request Body
POST https://api.crosscurve.fi/tx/create
Request Body
API link: https://api.crosscurve.fi
Explorer: https://explorer.eywa.fi/
GET https://api.crosscurve.fi/search?search={hashOrReqId}&limit={limit}
Query Parameters
GET https://api.crosscurve.fi/transaction/{reqId}
Path Parameters
Decryption of router operation codes:
params.tokenIn*
String
address of the token that the user is selling on the chainIdIn network
params.tokemOut*
String
address of the token that the user is buying on the chainIdOut network
params.amountIn*
String
query.params.tokenIn*
String
query.params.tokenOut*
String
query.params.amountIn*
String
query.slippage*
Number
amountIn*
String
amountInWithoutSlippage*
String
amountOut*
String
amountOutWithoutSlippage*
String
route*
Route
Uw - unwrap to native token
W - wrap native token
M - emergency mint
U - emergency unlock
params.chainIdIn*
Number
chainId of the sending network
params.chainIdOut*
Number
chainId of the receiving network
params*
Object
slippage*
Number
query*
Object
query.params*
Object
query.params.chainIdIn*
Number
query.params.chainIdOut*
Number
from*
String
recipient*
String
routing*
Routing
estimate*
Estimate
search*
String
hash or requestId of the transaction
limit*
String
reqId*
String
const requestRoutingParams = {
params: {
chainIdIn": 1, // Ethereum
chainIdOut: 250, // Fantom
tokenIn: "0xdac17f958d2ee523a2206206994597c13d831ec7", // USDT
tokenOut: "0xe71286fc887189c562410af12ed521c8e58e5fa3", // s3crypto_e
amountIn: "100000000", // 100 USDT
},
slippage: 1, // 1%
}
const response = await fetch('https://api.crosscurve.fi/routing/scan', {
method: 'POST',
body: JSON.stringify(requestRoutingParams),
headers: {
"Content-Type": "application/json",
},
})
const routing = await response.json()const bestRoute = routing[0]
const response = await fetch('https://api.crosscurve.fi/estimate', {
method: 'POST',
body: JSON.stringify(bestRoute),
headers: {
"Content-Type": "application/json",
},
})
const estimate = await response.json()const txCreateParams = {
from: '0x...', // sender
recipient: '0x...', // recipient
routing,
estimate,
}
const response = await fetch('https://api.crosscurve.fi/tx/create', {
method: 'POST',
body: JSON.stringify(txCreateParams),
headers: {
"Content-Type": "application/json",
},
})
const rawTx = await response.json()import { Contract, JsonRpcProvider } from 'ethers'
const provider = new JsonRpcProvider('RPC_URL_HERE')
const signer = new Wallet(process.env.PRIVATE_KEY, provider)
const router = new Contract(rawTx.to, [rawTx.abi], signer)
const args = [
rawTx.args[0],
rawTx.args[1],
[
rawTx.args[2].executionPrice,
rawTx.args[2].deadline,
rawTx.args[2].v,
rawTx.args[2].r,
rawTx.args[2].s,
],
]
const value = BigInt(rawTx.value) + BigInt(estimate.executionPrice)
const tx = await router.start(...args, { value })
const receipt = await tx.wait()const searchParams = new URLSearchParams({
search: '0x...', // transaction hash
limit: 1,
}).toString();
const response = await fetch(`https://api.crosscurve.fi/?${searchParams}`, {
method: 'GET',
})
const result = await response.json()
const details = result.result[0]
const requestId = details.requestId
TypeScriptconst response = await fetch(`https://api.crosscurve.fi/search?search=%7BhashOrReqId%7D&limit=%7Blimit%7D`, {
method: 'GET',
})
const details = await response.json()
const destination = details.destination
TypeScript[
{
"query": {
"params": {
"tokenIn": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"chainIdIn": 1,
"tokenOut": "0xe71286fC887189C562410af12eD521C8e58e5fA3",
"chainIdOut": 250,
"amountIn": "100000000"
},
"slippage": 0.5
},
"route": [
{
"type": "addLiquidity",
"chainId": 1,
"params": {
"tokenIn": {
"logos": {
"16": "https://s2.coinmarketcap.com/static/img/coins/16x16/825.png",
"32": "https://s2.coinmarketcap.com/static/img/coins/32x32/825.png",
"64": "https://s2.coinmarketcap.com/static/img/coins/64x64/825.png",
"128": "https://s2.coinmarketcap.com/static/img/coins/128x128/825.png",
"200": "https://s2.coinmarketcap.com/static/img/coins/200x200/825.png"
},
"chainId": 1,
"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"originalName": "Tether USD",
"originalSymbol": "USDT",
"tags": ["erc20", "stable"],
"permittable": false,
"permit": false
},
"chainIdIn": 1,
"tokenOut": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
},
"chainIdOut": 1,
"amountIn": "100000000",
"amountInWithoutSlippage": "100000000",
"amountOut": "54972421143512185",
"amountOutWithoutSlippage": "55248664465841392",
"slippage": 0.5
},
"pool": {
"address": "0xd51a44d3fae010294c616388b506acda1bfaae46",
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
"decimals": [6, 8, 18],
"logos": {
"16": "https://s2.coinmarketcap.com/static/img/exchanges/16x16/1063.png",
"32": "https://s2.coinmarketcap.com/static/img/exchanges/32x32/1063.png",
"64": "https://s2.coinmarketcap.com/static/img/exchanges/64x64/1063.png",
"128": "https://s2.coinmarketcap.com/static/img/exchanges/128x128/1063.png",
"200": "https://s2.coinmarketcap.com/static/img/exchanges/200x200/1063.png"
},
"lp": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
}
},
"fees": [
{
"type": "eywaStableSwapFee",
"token": {
"logos": {
"16": "https://s2.coinmarketcap.com/static/img/coins/16x16/825.png",
"32": "https://s2.coinmarketcap.com/static/img/coins/32x32/825.png",
"64": "https://s2.coinmarketcap.com/static/img/coins/64x64/825.png",
"128": "https://s2.coinmarketcap.com/static/img/coins/128x128/825.png",
"200": "https://s2.coinmarketcap.com/static/img/coins/200x200/825.png"
},
"chainId": 1,
"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"originalName": "Tether USD",
"originalSymbol": "USDT",
"tags": ["erc20", "stable"],
"permittable": false,
"permit": false
},
"percent": "0.0654473",
"amount": "65447"
}
]
},
{
"type": "bridgeIn",
"chainId": 1,
"params": {
"tokenIn": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
},
"chainIdIn": 1,
"tokenOut": {
"chainId": 250,
"address": "0xe71286fC887189C562410af12eD521C8e58e5fA3",
"name": "s3crypto_e",
"symbol": "s3crypto_e",
"decimals": 18,
"originalName": "s3crypto_e",
"originalSymbol": "s3crypto_e",
"tags": ["erc20", "synth"],
"permittable": false,
"permit": false,
"real": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
},
"realToken": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
}
},
"chainIdOut": 250,
"amountIn": "54972421143512185",
"amountInWithoutSlippage": "55248664465841392",
"amountOut": "54972421143512185",
"amountOutWithoutSlippage": "55248664465841392",
"slippage": 0.5
},
"fees": [
{
"type": "bridgeFee",
"amount": "0",
"percent": "0",
"token": {
"chainId": 250,
"address": "0xe71286fC887189C562410af12eD521C8e58e5fA3",
"name": "s3crypto_e",
"symbol": "s3crypto_e",
"decimals": 18,
"originalName": "s3crypto_e",
"originalSymbol": "s3crypto_e",
"tags": ["erc20", "synth"],
"permittable": false,
"permit": false,
"real": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
},
"realToken": {
"chainId": 1,
"address": "0xc4ad29ba4b3c580e6d59105fff484999997675ff",
"name": "Curve.fi USD-BTC-ETH",
"symbol": "crv3crypto",
"decimals": 18,
"originalName": "Curve.fi USD-BTC-ETH",
"originalSymbol": "crv3crypto",
"tags": ["erc20", "curve_lp"],
"permittable": false,
"permit": false,
"coins": [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
]
}
}
}
]
}
],
"amountIn": "100000000",
"amountOut": "54972421143512185",
"amountOutWithoutSlippage": "55248664465841392",
"tokenInPrice": 1,
"tokenOutPrice": 1811.0144629377985,
"priceImpact": 0,
"totalFee": {
"type": "total",
"percent": "0.07",
"amount": 0.06545
}
}
]{
"priceInDollars": "2.88",
"executionPrice": "1408116103514941",
"stablePrice": "0",
"workerFee": "1408116103514941",
"deadline": "1699876788",
"signature": "RiyQlohm2vpof3Nnab4cUwZ/mHey/Su"
}{
"to": "0x9af02523431E9Ec1Cc649c75aB0322fF34cde337",
"abi": "function start(string[],bytes[],tuple(uint256,uint256,uint8,bytes32,bytes32)) payable",
"args": [
["LM", "As", "Ss", "Rs", "BU"],
[
"0x0000000000000000000000002e1ad108ff1d8c782fcbbb89aad783ac495867560000000000000000000000000000000000000000000000019274b259f6540000000000000000000000000000bd2c008c3467393c6f342a275ec8f2ccd7b4f40d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd2c008c3467393c6f342a275ec8f2ccd7b4f40d",
"0x0000000000000000000000002827053d2f2c3ed312d2092e57d8537405fdfd0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054cc70a3324cac8308045d027415e4df82ee72b8000000000000000000000000000000000000000000000001906a0a6f860c0d89000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000",
"0x00000000000000000000000054cc70a3324cac8308045d027415e4df82ee72b8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da8a6f376f056f0b10980ef0756bd642bc3ecab00000000000000000000000000000000000000000000000018e421e43cc563e5a0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064d09662725ddc8d01a037618906a04326b9985f0000000000000000000000000000000000000000000000000000000000000000",
"0x00000000000000000000000064d09662725ddc8d01a037618906a04326b9985fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064d09662725ddc8d01a037618906a04326b9985f0000000000000000000000000000000000000000000000000000000001b3d1dc000000000000000000000000000000000000000000000000000000000000000300000000000000000000000074aeed349f3fcae9c158504686f9304c4bbfa39a0000000000000000000000000000000000000000000000000000000000000000",
"0x00000000000000000000000074aeed349f3fcae9c158504686f9304c4bbfa39affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd2c008c3467393c6f342a275ec8f2ccd7b4f40d000000000000000000000000000000000000000000000000000000000000a86a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
],
{
"executionPrice": "449952232019487626",
"deadline": "1698416184651",
"v": 28,
"r": "0x178afdb0baacdae7b6e0c920de67e2b981a3a8c141204f26c66f5d6d148cde0a",
"s": "0x5391489d89f6955281245896199baee4d3a983caf0af027ceb93aac62e5b743f"
}
],
"value": "0"
}{
"result": [
{
"requestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e",
"status": "completed",
"source": {
"chainId": "137",
"transactionHash": "0xad58de57530187afa410d3dc5356e843be0c123075a51fe38aeb46a7f0481133",
"from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"events": [
{
"args": {
"_to": "0xBf0b5D561b986809924f88099c4FF0e6BccE60c9",
"_from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2e1AD108fF1D8C782fcBbB89AAd783aC49586756",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"to": "0x0000000000000000000000000000000000000000",
"from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"token": "0x2e1AD108fF1D8C782fcBbB89AAd783aC49586756",
"amount": "29000000000000000000"
},
"name": "Locked",
"topic": "0xb5f411fa3c897c9b0b6cd61852278a67e73d885610724a5610a8580d3e94cfdb",
"address": "0xBf0b5D561b986809924f88099c4FF0e6BccE60c9",
"signature": "Locked(address,uint256,address,address)"
},
{
"args": {
"lastOp": 0,
"result": 1,
"nextChainId": "250",
"nextRequestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e",
"currentChainId": "137",
"currentRequestId": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"name": "ComplexOpProcessed",
"topic": "0x830adbcf80ee865e0f0883ad52e813fdbf061b0216b724694a2b4e06708d243c",
"address": null,
"signature": "ComplexOpProcessed(uint64,bytes32,uint64,bytes32,uint8,uint8)"
},
{
"args": {
"payer": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"accountant": "0x94a365CA808029AF8db18257ecd296c16C61AC05",
"executionPrice": "449952232019487626"
},
"name": "FeePaid",
"topic": "0xbf6afbaffb3b955bebbf43430bbf8eecb8d34ff86f293f592203ab5ed79c5268",
"address": null,
"signature": "FeePaid(address,address,uint256)"
}
]
},
"destination": {
"chainId": "250",
"transactionHash": "0x6969c46c4c8b239486e309155cf75b2b4ea2d1b7a8ca8a868155546cd9ce6edf",
"to": "0x1C61f207F50acAF3b15D1DE4eb7a02f290c3eE8A",
"events": [
{
"args": {
"_to": "0x4400671b8238B5E0c7c9d7572746d236cd292845",
"_from": "0x0000000000000000000000000000000000000000",
"_value": "0"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_from": "0x0000000000000000000000000000000000000000",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x54cc70A3324cAc8308045D027415e4Df82EE72B8",
"_from": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_from": "0x64D09662725dDc8D01a037618906a04326B9985f",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"_from": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x0000000000000000000000000000000000000000",
"_from": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"to": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"from": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"token": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"amount": "28994655"
},
"name": "Burn",
"topic": "0xc489dd211b01a11cf2d73490ca466baa426e76a7811070af00cc9a2bfd322f1c",
"address": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"signature": "Burn(address,uint256,address,address)"
},
{
"args": {
"lastOp": 4,
"result": 1,
"nextChainId": "43114",
"nextRequestId": "0x5d685648f8c21405956e570d0796055dcf330e3768cfd27e1d50a5e46c9a1fae",
"currentChainId": "250",
"currentRequestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e"
},
"name": "ComplexOpProcessed",
"topic": "0x830adbcf80ee865e0f0883ad52e813fdbf061b0216b724694a2b4e06708d243c",
"address": null,
"signature": "ComplexOpProcessed(uint64,bytes32,uint64,bytes32,uint8,uint8)"
}
]
}
}
],
"total": 1
}{
"status": "completed",
"inconsistency": false,
"source": {
"chainId": "137",
"transactionHash": "0xad58de57530187afa410d3dc5356e843be0c123075a51fe38aeb46a7f0481133",
"from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"events": [
{
"args": {
"_to": "0xBf0b5D561b986809924f88099c4FF0e6BccE60c9",
"_from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2e1AD108fF1D8C782fcBbB89AAd783aC49586756",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"to": "0x0000000000000000000000000000000000000000",
"from": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"token": "0x2e1AD108fF1D8C782fcBbB89AAd783aC49586756",
"amount": "29000000000000000000"
},
"name": "Locked",
"topic": "0xb5f411fa3c897c9b0b6cd61852278a67e73d885610724a5610a8580d3e94cfdb",
"address": "0xBf0b5D561b986809924f88099c4FF0e6BccE60c9",
"signature": "Locked(address,uint256,address,address)"
},
{
"args": {
"lastOp": 0,
"result": 1,
"nextChainId": "250",
"nextRequestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e",
"currentChainId": "137",
"currentRequestId": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"name": "ComplexOpProcessed",
"topic": "0x830adbcf80ee865e0f0883ad52e813fdbf061b0216b724694a2b4e06708d243c",
"address": null,
"signature": "ComplexOpProcessed(uint64,bytes32,uint64,bytes32,uint8,uint8)"
},
{
"args": {
"payer": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"accountant": "0x94a365CA808029AF8db18257ecd296c16C61AC05",
"executionPrice": "449952232019487626"
},
"name": "FeePaid",
"topic": "0xbf6afbaffb3b955bebbf43430bbf8eecb8d34ff86f293f592203ab5ed79c5268",
"address": null,
"signature": "FeePaid(address,address,uint256)"
}
],
"status": "completed"
},
"oracle": {
"relayChainId": "137",
"requestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e",
"status": "completed",
"height": "3942",
"epoch": 4,
"time": "2023-10-27T14:13:45.949Z"
},
"destination": {
"chainId": "250",
"transactionHash": "0x6969c46c4c8b239486e309155cf75b2b4ea2d1b7a8ca8a868155546cd9ce6edf",
"to": "0x1C61f207F50acAF3b15D1DE4eb7a02f290c3eE8A",
"events": [
{
"args": {
"_to": "0x4400671b8238B5E0c7c9d7572746d236cd292845",
"_from": "0x0000000000000000000000000000000000000000",
"_value": "0"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_from": "0x0000000000000000000000000000000000000000",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x54cc70A3324cAc8308045D027415e4Df82EE72B8",
"_from": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_value": "29000000000000000000"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x2827053d2F2c3ED312d2092e57D8537405fdFd0f",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_from": "0x64D09662725dDc8D01a037618906a04326B9985f",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"_from": "0x14F98dcf918a451a15f3A11d824C65906bDDc296",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"_to": "0x0000000000000000000000000000000000000000",
"_from": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"_value": "28994655"
},
"name": "Transfer",
"topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"address": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"signature": "Transfer(address,address,uint256)"
},
{
"args": {
"to": "0xBD2c008C3467393C6F342A275EC8F2Ccd7B4F40D",
"from": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"token": "0x74aEeD349F3Fcae9C158504686f9304C4Bbfa39A",
"amount": "28994655"
},
"name": "Burn",
"topic": "0xc489dd211b01a11cf2d73490ca466baa426e76a7811070af00cc9a2bfd322f1c",
"address": "0x530aF883f135F135BE12A69DC33296fb8149f593",
"signature": "Burn(address,uint256,address,address)"
},
{
"args": {
"lastOp": 4,
"result": 1,
"nextChainId": "43114",
"nextRequestId": "0x5d685648f8c21405956e570d0796055dcf330e3768cfd27e1d50a5e46c9a1fae",
"currentChainId": "250",
"currentRequestId": "0x5173910105f8c526ed1dbbac0dc3e0d1efd9b18b83f56d460a7a3dd09d4d198e"
},
"name": "ComplexOpProcessed",
"topic": "0x830adbcf80ee865e0f0883ad52e813fdbf061b0216b724694a2b4e06708d243c",
"address": null,
"signature": "ComplexOpProcessed(uint64,bytes32,uint64,bytes32,uint8,uint8)"
}
],
"status": "completed",
"emergency": false,
"error": null
},
"data": {
"callData": "0000000000000089f898c1cbab66ac331e48ad0854bdd7daeee8806c5a1342c68df5f8d3b5ba8c8bdab6060b0f5c53a9cf19a7eb0b478ac03faf58420ef143624e89feb96d5bdd9416d8208c06afb253d3b4d913a45f11f6661837a73706a9272680626e1b84b6c60000000002eefe7b0000000000000f6600000000653bc534",
"size": 128
}
}ss-chain liquidity protocol smart contracts (CrossCurve) are a type of self-executing digital agreement stored on a blockchain that automatically execute when predetermined terms and conditions are met. These contracts facilitate the creation of liquidity pools that enable decentralized trading, offering behaviors that are more predictable and in line with the primary principles of blockchain technology, such as trustless operations without susceptible governance. In general, smart contracts are designed to digitally facilitate, verify, or enforce the negotiation or performance of a contract. They allow transactions to be conducted without the need for intermediaries, while ensuring that these transactions are trackable and irreversible once completed.
Polygon
Avalanche
Optimism
Arbitrum
Fantom
Base
Gnosis
Mantle
Blast
Linea
Taiko
Unit0
Celo
Fraxtal
Kava
Metis
Mode
Sonic
Manta
Description
same as v1.5
same as v1.5
same as v1.5
v 2.51 (celo)
same as v1
same as v1
same as v2
xCRVUSDC
x3CRYPTO
xCRVUSDT
xSTABLE
xBTC
xSTABLE2
Ethereum
BNB
Ethereum
BSC
Polygon
Avalanche
Optimism
Arbitrum
Fantom
Base
Gnosis
Taiko
Celo
Fraxtal
Sonic
Description
n: 3
n: 3
n: 2
n: 3
n: 4
Aave, n: 3
stableNG/cryptoNG
n: 3
n: 2
n: 2
zap
Ethereum
0xb7ecb2aa52aa64a717180e030241bc75cd946726
Arbitrum
0x82670f35306253222f8a165869b28c64739ac62e
Arbitrum
0xec090cf6DD891D2d014beA6edAda6e05E025D93d
Arbitrum
0x73aF1150F265419Ef8a5DB41908B700C32D49135
Arbitrum
0x7f90122BF0700F9E7e1F688fe926940E8839F353
Arbitrum
0x186cf879186986a20aadfb7ead50e3c20cb26cec
Arbitrum
0xdadd23929ca8efcbc43aaf8f677d426563cc40d7
Arbitrum
0x6579758e9e85434450d638cfbea0f2fe79856dda
Polygon
0xdAD97F7713Ae9437fa9249920eC8507e5FbB23d3
Polygon
0xb0658482b405496c4ee9453cd0a463b134aef9d0
Polygon
0x5225010A0AE133B357861782B0B865a48471b2C5
Polygon
0xA70Af99bFF6b168327f9D1480e29173e757c7904
Polygon
0xE7a24EF0C5e95Ffb0f6684b813A78F2a3AD7D171
Polygon
0xA73EdCf18421B56D9AF1cE08A34E102E23b2C4B6
Avalanche
0x1daB6560494B04473A0BE3E7D83CF3Fdf3a51828
Avalanche
0x1dc5c0f8668a9f54ed922171d578011850ca0341
Avalanche
0x1337BedC9D22ecbe766dF105c9623922A27963EC
Optimism
0x03771e24b7C9172d163Bf447490B142a15be3485
Optimism
0x4456d13Fc6736e8e8330394c0C622103E06ea419
Optimism
0xD1b30BA128573fcd7D141C8A987961b40e047BB6
Optimism
0x1337BedC9D22ecbe766dF105c9623922A27963EC
BNB chain
0xC4Ec3aB41182E70cA45a764fFc5c45B9A82cCc97
BNB chain
0xAE87E5Fa20f335ce14AA3B9E0616308d9AC7d4Ce
BNB chain
0xA5E0E46462970C9Ee8C2ECadcde254c483748Ec4
Base
0x6e53131F68a034873b6bFA15502aF094Ef0c5854
Base
0xf6C5F01C7F3148891ad0e19DF78743D31E390D1f
Gnosis
0x1337BedC9D22ecbe766dF105c9623922A27963EC
Gnosis
0x7f90122BF0700F9E7e1F688fe926940E8839F353
Celo
0x28F209844029755FC563c1bD4FD21f42DC7CE0e4
Fraxtal
0xcAEF324bea3Ff5c7a08710081294F3344fFAdC54
Fantom
0x7d04f016749c215e52138b06bb35ee8491e739fd
Fantom
0x353bb1dfbc52bc3b0e7d264216b1455df00f50be
Fantom
0x5ecac5fb1d9634f9e1c2dab2381b9adaada5f80b
Fantom
0x3f833ed02629545dd78afc3d585f7f3918a3de62
Fantom
0xa3a63276b8668583e1b47b979d1093d9aaf431ee
Fantom
0x15ee0d5f92fd869c2fbf26ea785e9d150353568d
Fantom
0x3c2fcf53f742345c5c1b3dcb2612a1949bc1f18d
Fantom
0xabba40f628f055149f1c7415c4388363392279c3
Fantom
0x37F5dae6039C8eC4c32ad7D3e2a07aCaa55C08f9
Fantom
0x06a2e1521afde7f7dc30d351dcf04408042f536e
Sonic
0x38dd6b3c096c8cbe649fa0039cc144f333be8e61
Sonic
0xf1232a1ab5661abdd6e02c6d8ac9940a23bb0b84
Sonic
0x346704605c72d9f5f9f02d651e5a3dcce6964f3d
Sonic
0x4fe12cf68147e902f4ccd8a3d4c13e89fba92384
Sonic
0xf159c51297306839b7d44cbb5cb9360e4623ae5a
Sonic
0xdac15649b025ba0047718512111c34096e9545e8
Sonic
0xf821404ac19ac1786caca7e3e12658d72ece885e
Sonic
0x440bcab62d629ba60ca56b80e565636e0c404e60
Sonic
0xd9bf67d8a5d698a028160f62480d456801f0b4b1
Sonic
0x435a160ef111ad0aa0867bece7b85cb77dce3c8a
Sonic
0x90135d7300c690d786fa8fea071cd4c2ed080d16
Sonic
0x20c2e44bbbea698da4a4cb687514e66385996639
Sonic
0xedcf9ef9b389a8f52e81958d8212faf6fbd758ae
Sonic
0x6988d6eec3ca7d24c0358bab8018787117325c2b
Sonic
0x9e63e5d31fd0136290ef99b3cac4515f346fef1c
Sonic
0x2b0911095350785fb32a557d1d2e3b36a9bb9252
Sonic
0xaa186960df95495084ef1ddc40a3bdac22b0d343
Sonic
0xb7bb92ff0ec68e6d79a238174e42c12ff5ef2b00
Sonic
0x024cc841cd7fe4e7dd7253676c688146599923cf
Sonic
0x2e97cf8da26ce3858950dd85b8f69e39ebd251f5
Sonic
0x24479a0d48849781b4386ed91fdd84241673ab1e
Sonic
0x9ccaabd2610d467b1f76c8aacec4f567ec61d78e
Sonic
0x424757a5169e1f3b45436c9b2e5421dc39dc4897
Sonic
0xa5a5da9c386855b199b8928cbb59c7ac6505ba89
Sonic
0x6f6522261f89d988d5f5caa5e4e658344517b114
Sonic
0x13882f7f207329db487ce99839c26392a233d97b
Sonic
0xeb427d3cc29ec4c49e48fccc580b11f15d7d096d
Sonic
0xdbb986d7fef61260c7f9a443e62e8a91974c5e3d
Sonic
0xa4948da3f2007193dd7404278fed15d48c617417
Sonic
0x8bb9b3e45fa6b4bf4bbb66ad09f485c5509a0e4c
Sonic
0x601538c805ea9d83a49c132f18417db9666f69d5
Sonic
0x759a32b417bb471da76cf41ca2ea42f4e0b143eb
Sonic
0xe5a0813a7de6abd8599594e84cb23e4a6d9d9800
Sonic
0x6d9f0ff2b7f1397ee731f6370d8e4699ffad7bc5
Sonic
0x1008358eecb59723391fba0f8a6b36c5346dab2d
Sonic
0x09679c768d17b52bfa059010475f9a0bdb0d6fea
Sonic
0x1c404afffba0e70426dc601aeaa6205eca8c9078
Sonic
0x7b823067ece11047f83f48647110e7a777e2bf5a
Sonic
0x538a5534543752d5abbc8cd11760f8be3625e7b1
Sonic
0xdb0a43327626c0e3e87ce936bc0cdf2ee9475c22
Sonic
0x5fa5168497db4ec1964b3208c18cb6157e5652e4
Sonic
0x1894a7203faa464f7afa3b8c319a3cac8beb6cda
Sonic
0xee05755051e8b1ccf85747a83d0ef8b00f161180
Sonic
0x9b78e02ddddda4117ddf6be8a0fbd15c45907895
Sonic
0x3301e4326cf2939cd6b8f23ddf7bc2a1713fd06a
Taiko
0xB391F2D5B83B3900997B4D6880ba7818Bef3591a
Ethereum
0x70980bD7253f8150dDD973CB430374Adaa0A143F
Ethereum
0xf939e0a03fb07f59a73314e73794be0e57ac1b4e
Ethereum
0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Ethereum
0xdac17f958d2ee523a2206206994597c13d831ec7
Ethereum
0x6b175474e89094c44da98b954eedeac495271d0f
Ethereum
0x73a15fed60bf67631dc6cd7bc5b6e8da8190acf5
Ethereum
0x35d8949372d46b7a3d5a56006ae77b215fc69bc0
Ethereum
0x853d955acef822db058eb8505911ed77f175b99e
Ethereum
0x4c9edd5852cd905f086c759e8383e09bff1e68b3
Ethereum
0x83f20f44975d03b1b09e64809b757c47f942beea
Ethereum
0x9d39a5de30e57443bff2a8307a4256c8797a3497
Ethereum
0xad55aebc9b8c03fc43cd9f62260391c13c23e7c0
Ethereum
0xbdc7c08592ee4aa51d06c27ee23d5087d65adbcd
Ethereum
0x15700b564ca08d9439c58ca5053166e8317aa138
Ethereum
0x865377367054516e17014ccded1e7d814edc9ce4
Ethereum
0x6c3ea9036406852006290770bedfcaba0e23a0e8
Ethereum
0x085780639cc2cacd35e474e71f4d000e2405d8f6
Ethereum
0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f
Ethereum
0x66a1e37c9b0eaddca17d3662d6c05f4decf3e110
Ethereum
0xD533a949740bb3306d119CC777fa900bA034cd52
Ethereum
0x2260fac5e5542a773aa44fbcfedf7c193bc2c599
Ethereum
0x18084fbA666a33d37592fA2633fD49a74DD93a88
Ethereum
ETH
native coin
Ethereum
0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arbitrum
0x7A10F506E4c7658e6AD15Fdf0443d450B7FA80D7
Arbitrum
0xD9879D9DbDc5042D8f1C2710Be293909B985dc90
Arbitrum
0x498bf2b1e120fed3ad3d42ea2165e9b73f99c1e5
Arbitrum
0xff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arbitrum
0xaf88d065e77c8cC2239327C5EDb3A432268e5831
Arbitrum
0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9
Arbitrum
0x59d9356e565ab3a36dd77763fc0d87feaf85508c
Arbitrum
0x12275dcb9048680c4be40942ea4d92c74c63b844
Arbitrum
0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978
Arbitrum
0x912CE59144191C1204E64559FE8253a0e49E6548
Arbitrum
0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f
Arbitrum
0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40
Arbitrum
0x050C24dBf1eEc17babE5fc585F06116A259CC77A
Arbitrum
ETH
native coin
Arbitrum
0x82af49447d8a07e3bd95bd0d56f35241523fbab1
Arbitrum
0x21ab704b2cdf792e1e84f591ca082fff8de12198
Arbitrum
0xe80698d9c55d9212c4dae8bed00e1357d804c62a
Arbitrum
0x21b1b07af26613479e526c058749239e460f8a2f
Arbitrum
0x432D9C4Cc7021dDcF6e1D2Af4886dd29d7709582
Optimism
0xc52d7f23a2e460248db6ee192cb23dd12bddcbf6
Optimism
0x7F5c764cBc14f9669B88837ca1490cCa17c31607
Optimism
0x94b008aA00579c1307B0EF2c499aD98a8ce58e58
Optimism
0xda10009cbd5d07dd0cecc66161fc93d7c9000da1
Optimism
0x0994206dfe8de6ec6920ff4d779b0d950605fb53
Optimism
0x68f180fcCe6836688e9084f035309E29Bf0A2095
Optimism
0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40
Optimism
ETH
native coin
Optimism
0x4200000000000000000000000000000000000006
Optimism
0x21b1b07af26613479e526c058749239e460f8a2f
Avalanche
0xd586e7f844cea2f87f50152665bcbc2c279d8d70
Avalanche
0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664
Avalanche
0xc7198437980c041c805a1edcba50c1ce5db95118
Avalanche
0x47afa96cdc9fab46904a55a6ad4bf6660b53c38a
Avalanche
0x46a51127c3ce23fb7ab1de06226147f446e4a857
Avalanche
0x532e6537fea298397212f09a61e03311686f548e
Avalanche
0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7
Avalanche
0x111111111111ed1D73f860F57b2798b683f2d325
Avalanche
0x130966628846BFd36ff31a822705796e8cb8C18D
Avalanche
0x152b9d0FdC40C096757F570A51E494bd4b943E50
Avalanche
0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB
Polygon
0xc4ce1d6f5d98d65ee25cf85e9f2e9dcfee6cb5d6
Polygon
0x2791bca1f2de4661ed88a30c99a7a9449aa84174
Polygon
0x1a13f4ca1d028320a707d99520abfefca3998b7f
Polygon
0xc2132d05d31c914a87c6611c10748aeb04b58e8f
Polygon
0x60d55f02a771d515e077c9c2403a1ef324885cec
Polygon
0x8f3cf7ad23cd3cadbd9735aff958023239c6a063
Polygon
0x27f8d03b3a2196956ed754badc28d73be8830a6e
Polygon
0x172370d5cd63279efa6d502dab29171933a610af
Polygon
0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6
Polygon
0x7ceb23fd6bc0add59e62ac25578270cff1b9f619
Polygon
0x21b1b07af26613479e526c058749239e460f8a2f
BSC
0x7A10F506E4c7658e6AD15Fdf0443d450B7FA80D7
BSC
0xe2fb3f127f5450dee44afe054385d74c392bdef4
BSC
0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409
BSC
0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d
BSC
0x55d398326f99059fF775485246999027B3197955
BSC
0xf3527ef8dE265eAa3716FB312c12847bFBA66Cef
BSC
0x7788A3538C5fc7F9c7C8A74EAC4c898fC8d87d92
BSC
0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c
BSC
0x2170Ed0880ac9A755fd29B2688956BD959F933F8
BSC
0xe80698d9c55d9212c4dae8bed00e1357d804c62a
BSC
0x21b1b07af26613479e526c058749239e460f8a2f
Base
0x417Ac0e078398C154EdFadD9Ef675d30Be60Af93
Base
0x646A737B9B6024e49f5908762B3fF73e65B5160c
Base
0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA
Base
0xEB466342C4d449BC9f53A865D5Cb90586f405215
Base
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Base
0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C
Base
0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415
Base
0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf
Base
ETH
native coin
Base
0x4200000000000000000000000000000000000006
Base
0xDBFeFD2e8460a6Ee4955A68582F85708BAEA60A3
Gnosis
0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83
Gnosis
0x4ECaBa5870353805a9F068101A40E0f32ed605C6
Gnosis
0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d
Gnosis
0xcB444e90D8198415266c6a2724b7900fb12FC56E
Gnosis
0x54E4cB2a4Fa0ee46E3d9A98D13Bea119666E09f6
Gnosis
0x712b3d230f3c1c19db860d80619288b1f0bdd0bd
Gnosis
0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1
Gnosis
0x8e5bbbb09ed1ebde8674cda39a0c169401db4252
Blast
0x4300000000000000000000000000000000000003
Blast
ETH
native coin
Blast
0x4300000000000000000000000000000000000004
Blast
0xf08e269cd00c4713fe880d4c550f779d329b6f48
Mantle
0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9
Mantle
0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111
Mantle
0xf08e269cd00c4713fe880d4c550f779d329b6f48
Linea
0x176211869cA2b568f2A7D4EE941E073a821EE1ff
Linea
0x3aab2285ddcddad8edf438c1bab47e1a9d05a9b4
Linea
ETH
native coin
Linea
0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f
Linea
0xf08e269cd00c4713fe880d4c550f779d329b6f48
Taiko
0xc8F4518ed4bAB9a972808a493107926cE8237068
Taiko
0x07d83526730c7438048D55A4fc0b850e2aaB6f0b
Taiko
0x2def195713cf4a606b49d07e520e22c17899a736
Taiko
ETH
native coin
Taiko
0xa51894664a773981c6c112c43ce576f315d5b1b6
Kava
0x919C1c267BC06a7039e03fcc2eF738525769109c
Celo
0xceba9300f2b948710d2653dd7b07f33a8b32118c
Celo
0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e
Celo
0x765de816845861e75a25fca122bb6898b8b1282a
Fraxtal
0x4d15ea9c2573addaed814e48c148b5262694646a
Fraxtal
0x331b9182088e2a7d6d3fe4742aba1fb231aecc56
Fraxtal
0xfc00000000000000000000000000000000000001
Fraxtal
0xfc00000000000000000000000000000000000006
Metis
0xbB06DCA3AE6887fAbF931640f67cab3e3a16F4dC
Metis
0x420000000000000000000000000000000000000A
Metis
0xf08e269cd00c4713fe880d4c550f779d329b6f48
Mode
0xd988097fb8612cc24eeC14542bC03424c656005f
Mode
0x4200000000000000000000000000000000000006
Manta
0xf417F5A458eC102B90352F697D6e2Ac3A3d2851f
Manta
0x0Dc808adcE2099A9F62AA87D9670745AbA741746
Mantle
0x09bc4e0d864854c6afb6eb9a9cdf58ac190d0df9
Unit Zero
GjwAHMjqWzYR4LgoNy91CxUKAGJN79h2hseZoae4nU8t
Unit Zero
0xCF43F7703d9B4E8835f977eF364B4014fA7e856E
Unit Zero
0xEb19000D90f17FFbd3AD9CDB8915D928F4980fD1
Unit Zero
0xb303d80db8415FD1d3C9FED68A52EEAc9a052671
Unit Zero
0x1B100DE3F13E3f8Bb2f66FE58c1949c32E71248B
Unit Zero
0x9CE808657ba90C65a2700b1cA5D943eC72834B52
Fantom
0x28a92dde19D9989F39A49905d7C9C2FAc7799bDf
Fantom
0x2F733095B80A04b38b0D10cC884524a3d09b836a
Fantom
0xE6c259bc0FCE25b71fE95A00361D3878E16232C3
Fantom
0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83
Sonic
0x29219dd400f2bf60e5a23d13be72b486d4038894
Sonic
0x6047828dc181963ba44974801FF68e538dA5eaF9
Sonic
0xd3dce716f3ef535c5ff8d041c1a41c3bd89b97ae
Sonic
0x80eede496655fb9047dd39d9f418d5483ed600df
Sonic
0x50c42dEAcD8Fc9773493ED674b675bE577f2634b
Sonic
0x3bce5cb273f0f148010bbea2470e7b5df84c7812
Sonic
0x43edd7f3831b08fe70b7555ddd373c8bf65a9050
Sonic
0xBb30e76d9Bb2CC9631F7fC5Eb8e87B5Aff32bFbd
Sonic
0xe5da20f15420ad15de0fa650600afc998bbe3955
Sonic
0x3301e4326cf2939cd6b8f23ddf7bc2a1713fd06a
Ethereum
0xd51a44d3fae010294c616388b506acda1bfaae46
Ethereum
0x4dece678ceceb27446b35c672dc7d61f30bad69e
Ethereum
0x390f3595bCa2Df7d23783dFd126427CCeb997BF4
Ethereum
0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490
CrossCurve pools and assets are integrated within the Sonic (previously Fantom) and Arbitrum ecosystems.
CrossCurve facilitates the swapping of s-tokens within Curve pools on the Sonic (in archive pools also Fantom), Arbitrum and Taiko Hubchains. All liquidity in CrossCurve on Hubchain is composed of s-tokens. These s-tokens are collateralized synthetic assets issued by the CrossCurve Consensus Bridge. Each s-token is fully backed by the original asset to which it is pegged, with these assets securely locked in the CrossCurve Token Bridge on the source blockchain. Audited by SmartState.
Specialized tokenized assets that facilitate cross-chain trading and yield generation. These s-tokens, typically part of CrossCurve's core stable pools, enable the exchange of similar tokens, thereby creating a unified cross-chain liquidity market. By aggregating liquidity across various blockchains, s-tokens play a pivotal role in streamlining cross-chain operations and enhancing the efficiency of decentralized trading within the Curve-based protocol.
Each paired pool on the Sonic (or Taiko) Hubchain consists of two tokens:
A universal token – an asset from Sonic, uniform across all pools of the same type (e.g., xfrxUSD for USD assets, xfrxETH for ETH, and scBTC for BTC). More details
For archived pools on , each different body of the name, such as "crvUSDT," specifies the supported pool:
crvUSDT - xCRVUSDT pool
crvUSDC - xCRVUSDC pool
3CRV - xCRVUSDT, xCRVUSDC, xSTABLE pools
CrossCurve supports the use of both standard assets and LP tokens as collateral for s-tokens. Below, you will find a list of cross-chain pools, the s-tokens they contain, and the assets backing them.
Pool page:
Pool/token:
CrossCurve frxUSD pool assets:
Pool page:
Pool/token:
CrossCurve frxETH pool assets:
Pool page: Pool/token: CrossCurve Stable ETH pool assets:
Pool page: Pool/token: CrossCurve Stable BSC pool assets:
Pool page: Pool/token: CrossCurve Stable AVA pool assets:
Pool page: Pool/token: CrossCurve Stable POL pool assets:
Pool page: Pool/token: CrossCurve Stable ARB pool assets:
Pool page: Pool/token: CrossCurve Stable OP pool assets:
Pool page: Pool/token: CrossCurve Stable BASE pool assets:
Pool page: Pool/token: CrossCurve Stable BL pool assets:
Pool page: Pool/token: CrossCurve Stable GNO pool assets:
CrossCurve Stable MTL
Pool page: Pool/token: CrossCurve Stable MTL pool assets:
Pool page: Pool/token: CrossCurve Stable LIN pool assets:
Pool page: Pool/token: CrossCurve Stable CELO pool assets:
Pool page: Pool/token: CrossCurve Stable MET pool assets:
Pool page: Pool/token: CrossCurve Stable MODE pool assets:
Pool page: Pool/token: CrossCurve Stable MTA pool assets:
Pool page: Pool/token: CrossCurve Stable KAVA pool assets:
Pool page: Pool/token: CrossCurve WETH ETH pool assets:
Pool page: Pool/token: CrossCurve WETH ARB pool assets:
Pool page: Pool/token: CrossCurve WETH OP pool assets:
CrossCurve WETH BASE
Pool page: Pool/token: CrossCurve WETH BASE pool assets:
Pool page: Pool/token: CrossCurve WETH BL pool assets:
Pool page: Pool/token: CrossCurve WETH MTL pool assets:
Pool page: Pool/token: CrossCurve WETH BSC pool assets:
Pool page: Pool/token: CrossCurve WETH POL pool assets:
Pool page: Pool/token: CrossCurve WETH AVA pool assets:
Pool page: Pool/token: CrossCurve WETH GNO pool assets:
Pool page: Pool/token: CrossCurve WETH MET pool assets:
Pool page: Pool/token: CrossCurve WETH MODE pool assets:
Pool page: Pool/token: CrossCurve WETH LIN pool assets:
Pool page: Pool/token: CrossCurve WETH MTA pool assets:
Pool page: Pool/token: CrossCurve BTC ETH pool assets:
Pool page: Pool/token: CrossCurve BTC ARB pool assets:
Pool page: Pool/token: CrossCurve BTC OP pool assets:
Pool page: Pool/token: CrossCurve BTC AVA pool assets:
Pool page: Pool/token: CrossCurve BTC POL pool assets:
Pool page: Pool/token: CrossCurve BTC BSC pool assets:
Pool page: Pool/token: CrossCurve BTC BASE pool assets:
Pool page: Pool/token: CrossCurve BTC LIN pool assets:
Pool page: Pool/token: CrossCurve BTC GNO pool assets:
Pool page:
Pool/token:
CrossCurve xCRV pool assets:
Pool page:
Pool/token:
CrossCurve xCRV2 pool assets:
Pool page:
Pool/token:
CrossCurve CRV/USD pool assets:
Pool page:
Pool/token:
CrossCurve cmGEMS1 pool assets:
CrossCurve Stable TAI
Pool page: Pool/token: CrossCurve Stable TAI pool assets:
Pool page: Pool/token: CrossCurve WETH TAI pool assets:
Pool page:
Pool/token:
CrossCurve EYWAUSDT pool assets:
Pool page:
Pool/token:
UNIT0/WUNIT0 pool assets:
Pool page:
Pool/token:
3UNIT0 pool assets:
CrossCurve Stable pool
Pool page:
Pool/token:
CrossCurve Stable pool assets:
CrossCurve WETH pool
Pool page:
Pool/token:
CrossCurve Stable pool assets:
Pool page:
Pool/token:
Pool page:
Pool/token:
CrossCurve xSTABLE pool assets:
Pool page:
Pool/token:
CrossCurve xSTABLE2 pool assets:
Pool page:
Pool/token:
CrossCurve xSTABLE3 pool assets:
Pool page:
Pool/token:
CrossCurve xWETH pool assets:
Pool page:
Pool/token:
CrossCurve xWETH2 pool assets:
Pool page:
Pool/token:
CrossCurve xBTC pool assets:
Pool page:
Pool/token :
CrossCurve 3crypto pool assets:
Pool page:
Pool/token :
CrossCurve crvUSDC pool assets:
Pool page:
Pool/token :
CrossCurve crvUSDT pool assets:
A synthetic derivative (s-token), backed by the original asset locked in the Consensus Bridge. These can be either single assets or LP tokens from Curve.
Synthetic tokens are categorized into three types:
s_Stable_chain, where Stable represents a USD asset variant, and chain is the network where the asset is used.
s_WETH_network, where WETH represents ETH backing, and chain is the network where the asset is used.
s_WBTC_network, where WBTC represents BTC backing, and chain is the network where the asset is used.
Each type of synthetic token corresponds to a pool where it can be paired in an LP token:
xs_chain, where xs is a stable pool, and chain is the network where the asset is used.
xe_chain, where xe is a volatile pool, and chain is the network where the asset is used.
xb_chain, where xb is a volatile pool, and chain is the network where the asset is used.
The suffix after an underscore, such as "eth," represents the network on which the token operates. For instance, "eth" might denote the Ethereum network.
In this naming structure, "sUSDT_eth" would represent a synthetic version of the CrossCurve s-token operating on the Ethereum network, to work with the liquidity in the CrossCurve Stable ETH pool.
Each different suffix corresponds to other supported networks, providing a quick reference to the cross-chain capabilities of the s-token within the CrossCurve platform:
eth - Ethereum network
arb - Arbitrum network
op - Optimism network
av - Avalanche network
p - Polygon network
b - Binance Smart Chain network
ba - Base network
g - Gnosis network
m - Mantle network
me - Metis network
mo - Mode network
ma - Manta network
bl - Blast network
l - Linea network
c - Celo network
ka - Kava nework
2CRV, 3Pool, 4Pool - xSTABLE pool
USDC, USDT, USDB, USDCe, 3pool, FrUsdt, USDt - xSTABLE2, xSTABLE3 pools
WETH - xWETH, xWETH2 pools
ETH, wfrxETH - xWETH2 pool
2BTC, BTC.b, WBTC, BTCB, cbBTC - xBTC pool
CRV, CRVTRI - xCRV pool
xs_chain, where xs is a stable pool, and chain is the network where the asset is used.
Ethereum
BSC
Avalanche
Polygon
Arbitrum
Optimism
Base
Blast
Sonic
Gnosis
Gnosis
Gnosis
Gnosis
Mantle
Linea
Celo
Metis
Mode
Manta
Kava
xe_chain, where xe is a volatile pool, and chain is the network where the asset is used.
Ethereum
Arbitrum
Optimism
Base
Blast
Mantle
BSC
Polygon
Avalanche
Gnosis
Metis
Mode
Linea
Manta
xb_chain, where xb is a volatile pool, and chain is the network where the asset is used.
Ethereum
Arbitrum
Optimism
Avalanche
Polygon
BSC
Base
Linea
Gnosis
Base
Optimism
Polygon
Gnosis
Fraxtal
Fantom
Sonic
Sonic
Taiko
Taiko
Taiko
Taiko
Optimism
Avalanche
Polygon
BSC
Base
Gnosis
Blast
Linea
Taiko
Celo
Fraxtal
Kava
Metis
Mode
Fantom
Fantom
Manta
Sonic
Mantle
Blast
Linea
Taiko
Gnosis
Metis
Mode
Optimism
Avalanche
Polygon
BSC
Base
Linea
Avalanche
Polygon
Optimism
Polygon
BNB chain
(3pool)
Avalanche
Optimism
Polygon
BNB chain
Avalanche
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Ethereum
Arbitrum
Sonic
Taiko
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Sonic
Arbitrum
Arbitrum
synth - Ethereum UNIT0
Arbitrum
synth - Units WUNIT0
Arbitrum
synth - Units WUNIT0
Arbitrum
Arbitrum
Arbitrum
Taiko
Taiko
Token
Source chain
Taiko
Taiko
Fantom
Fantom
Ethereum
Arbitrum
Fantom
Mantle
Fantom
Fantom
Ethereum
Arbitrum
Optimism
Base
Avalanche
Polygon
BSC
Fraxtal
Ethereum
Arbitrum
Ethereum
Arbitrum
Ethereum
Arbitrum
Ethereum
Arbitrum