Providing liquidity in DeFi, particularly to correlated trading pairs such as ETH LSTs/LRTs and stablecoins on decentralized exchanges (DEXs), or to lending markets like AAVE, Fluid, and Morpho, can be an extremely efficient onchain way to earn additional yield on one's assets. Despite this, it comes with many complexities to achieve that efficiency. Tokemak's Autopilot was developed to address the many challenges liquidity providers (LPs) face when optimizing for best performance. No protocol currently offers fully autonomous, transparent and sophisticated rebalance solution focused solely on liquidity provision. This dedicated approach offers great value not only to LPs, but also to a wide range of other ecosystem participants, making LP accessible.
Liquidity providers (LPs) face a highly complex decision-making process when seeking to optimally rebalance their LP positions. It requires an LP to account for a complex set of factors, including but not limited to:
variance of yields and their composition;
different fee and reward systems;
offsetting various costs such as gas, slippage, and trading fees;
different AMM models.
Differentiating between AMM models warrants highlighting, as its complexity is an often neglected core challenge of manual liquidity provision. Additional factors complicating the process include the significant amount of time LPs must spend researching opportunities and interacting with multiple protocols, making the process time-consuming and cumbersome. Even without considering these problems, the high costs of rebalancing and compounding often lead to underperformance and can prevent LPs from participating altogether.
Autopilot, a novel LP Aggregator, unlocks a new way to LP through Autopools. Users deposit assets into an Autopool, each representing a set of potential deployment destinations for the Autopilot.
From there, Autopilot takes over, autonomously monitoring the underlying pools and leveraging its powerful logic to rebalance – thus abstracting the complexity associated with rebalancing, compounding, and staking of LP tokens away from the user. The Autopool receipt tokens (e.g., autoETH) are yield-bearing and can be seamlessly integrated across DeFi.
The user experience is simple:
LP chooses an Autopool, deposit any asset via a simple, gas-optimized transaction and gets back the yield-bearing receipt token (e.g. autoETH)
Autopilot monitors the underlying destinations and rebalances
Autopilot auto-compounds rewards back into the Autopool
LP uses Dashboard to keep track of the Autopool's performance and other metrics
Providing liquidity to a set of destinations becomes as simple as swapping tokens or making a simple deposit.
"What DEX aggregators did for traders, Autopilot is doing for LPs."
Learn more about using Autopilot in the App Guide.
The purpose of Autopilot is to continuously rebalance assets from the Autopool into destinations with the best risk-return profiles, aiming to outperform any individual destination within the Autopool over the long term. Earnings are auto-compounded back into the Autopool and subsequently rebalanced. To achieve this, Autopilot does not merely chase the highest advertised yield but instead processes a comprehensive set of data, applies sophisticated logic, and adheres to safety constraints. This section will provide an accessible overview of the system's general architecture and essential features.
This section provides a simplified overview of the components, their functions within the Autopilot system, and a summary of the rebalance logic to help users achieve a basic understanding of the Autopilot system.
To understand the general architecture and functioning of the system, it helps to consider a simplified flow of assets within the system
This section provides a simplified overview of the components, their functions within the Autopilot system, and a summary of the rebalance logic to help users achieve a basic understanding of the Autopilot system.
For a comprehensive breakdown of the system, its components, and functionality, please refer to the Developer docs.
Autopilot, when viewed as a system and not as a product or concept, is comprised of multiple components that as a whole fulfill the purpose of continuously rebalancing assets from an Autopool into the destinations with the best risk/return profile.
Autopools are the system component which the user interacts with directly by depositing and withdrawing the base asset, the Autopool returning the depositor a receipt token. Autopools use the ERC-4626 standard and represents a fixed set of destinations (pools and DEXs) to which assets may be deployed to.
The Stats System is responsible for making various signals available on-chain and keeping the destination data up-to-date. These signals are then stored and processed by “calculators” that are kept up to date through a keeper network. Other system components rely on the data to get an accurate picture of the destination (e.g. trading fees).
Simply put, the Solver is an off-chain component that listens to opportunities to rebalance into higher yielding destinations and finds the path and timing for rebalances, which it proposes to the Strategy for validation. Inversely, it will also solve for and propose solutions to rebalance out of destinations that violate safety constraints. This is similar to how off-chain swap routing software (DEX aggregators) will find and split up trades between many pools to get the best price.
This explanation will highlight a few of the components and steps necessary to arrive at a valid rebalance solution.
Autopilot does not simply chase the highest yield, but processes a comprehensive set of data in order to attain long-term rather than short-term outperformance. The Stats System is collecting, storing and processing this data, for example:
APR and it's different components:
ETH Staking Yield: ETH yield generated by Consensus and Execution Layer rewards
Fee APR: Yield generated from swap fees
Incentive APR: Additional rewards paid to liquidity providers
Price return:
Exchange rate vs underlying ETH backing
Rebalancing costs:
Gas fees
Slippage
Trading fees
The above factors are weighted in order to account for e.g. likelihood of APR stability. More detail on the different yield types and APR weights can be found here.
Based on the data made available by the Stats System, the Solver proposes rebalance solutions to interchangeably convert assets and LP tokens, as well as LP token into other LP tokens. The rebalance solutions are proposed to the Strategy backing the Autopool. The Strategy verifies on-chain the validity of the proposal and adherence to immutable constraints, also by use of the Stats System's data. Among the strategy’s key features we have the following:
Composite Return Metric - The Composite Return Metric is a score associated with destinations for liquidity within Autopools. This metric breaks down APRs into separate parts. As such, Autopilot has the flexibility of overweighting/underweighting different components for further optimization. A valid rebalance needs to observe an increase of this metric.
Adaptive Rebalance Offset Period - The adaptive rebalance constraint is a gatekeeping condition for rebalances, which states that the expected return associated with a rebalance needs to be recouped over a given period. It is worth noting that this is a self-learning mechanism with a variable cost offset period that adapts to different market environments based on the observed yield volatility.
Lastly, the Strategy has a multitude of additional immutable constraints, such as the total slippage (i.e. total difference in the value of the in and out LP tokens), as well as lookback tests that validate an increase in net asset value (NAV) over time. Once fully validated by the Strategy, the rebalance proposal is executed.
To understand the general architecture and functioning of the system, it helps to consider a simplified flow of assets within the system:
Deposit – User deposits assets into Autopool. After this action, the Autopool has idle assets and the user gets the respective receipt token in return;
Rebalance – After a certain threshold of assets are deposited into the Autopool the Strategy backing it starts to accept proposals from the Solver. Once a proposal satisfies the constraints imposed by the Strategy, the assets in the Autopool are sent to the Solver which will then return LP tokens to the Autopool;
Auto-compounding – On a periodic basis, rewards from destinations are claimed and collected via a keeper process. These tokens are then converted into the Autopool base asset;
Debt Reporting – Each Autopool goes through a debt reporting where the system re-values the LP tokens held by that Autopool. During that process, any available auto-compounded rewards are claimed and come into the Autopool as idle funds;
Restart – With sufficient idle assets in the Autopool, another rebalance can occur.
In other words, users deposit assets into Autopools, the stats contracts provide on-chain information about the market, and the solver proposes rebalances to the strategy. To be accepted, the proposed rebalance must meet the strategy's constraints. The above outline focused on idle → LP rebalances but the rebalance step can occur for LP → LP rebalances as well. So long as the proposal results in a higher potential return (and satisfies other constraints) it can be executed.
Users gain access to Autopilot by depositing into an Autopool, which use the highly composable ERC-4626 standard and can be configured with a set of destinations (pools/DEXs and lending markets for some Autopools) to which assets may be deployed to. Assets deposited into an Autopool are not subject to any lock ups or cooldown periods, meaning that users can withdraw their funds at any time. The architecture was designed to be modular, allowing for plug-and-play integration of new assets and destinations. As a result, the system can adapt to the market swiftly by launching Autopools which include e.g. a new pairings, or cater to specific ecosystems.
LPs depositing into an Autopool receive reward bearing receipt tokens, or Liquid Auto Tokens (LATs), which are composable across DeFi. Examples of common DeFi integrations include utilizing LATs as collateral, integrating LATs into yield marketplaces to trade liquidity rates, and leverage LATs.
The sTOKE system is Tokemak's staking mechanism that enables active ecosystem participation. By staking TOKE, users receive credits that they can allocate to different Autopools. This allocation provides access to both reward streams and, when available, additional incentives specific to each Autopool.
Users can stake TOKE tokens for durations between 4 and 16 weeks, during which their TOKE converts to sTOKE and generates credits that can be allocated to Autopools. The staking duration directly affects the boost multiplier - longer staking periods result in higher credit generation. This system balances rewards for protocol commitment while accommodating various user preferences.
Once your TOKE is staked, your credits will by default be evenly allocated to the available Autopools. The default allocation will be applied to any newly staked TOKE.
You have complete flexibility in how you want to allocate your available credits across Autopools:
You can allocate to multiple Autopools simultaneously.
Allocation can be modified at any time without unstaking:
Adjust your allocations across Autopools at any time
Monitor and optimize your credit allocation based on performance
Your allocation of credits can be adjusted at any time, but reward calculations for the updated allocation take effect following the next snapshot. Note: when allocations are changed pre-snapshot, users will continue to earn rewards based on their previous allocation until the new snapshot goes live.
The distribution of credits is snapshotted weekly, with each snapshot determining reward distribution for the following week. This means rewards are backward-looking and are earned based on the voting snapshot at the beginning of each week.
For users looking to allocate voting credits to Autopools on different chains, TOKE is required to be present on the specific chain. A seamless bridging solution is available to transfer your TOKE across networks, located in the Staking (or sTOKE) section of the UI.
Read more about Staking TOKE in the App Guide here.
sTOKE holders who allocate their credits to Autopools earn rewards from multiple sources:
Rewards generated by the specific Autopools
Additional benefits from protocol-owned asset deployment
These are used to purchase TOKE to be distributed to the TOKE stakers.
The reward structure is designed to align user incentives with the protocol's long-term success, encouraging active participation in the ecosystem's growth.
Learn how to claim your rewards here.
Autopools are in essence customizable networks of automated liquidity, tokenized and made composable by their respective LAT. This allows for a new way to combine utility with distribution. For instance, an Autopool tailored for the XYZ DEX, featuring a custom selection of pools (e.g., correlated ETH pairs), which then distributes branded LAT tokens (e.g., xyzETH) to LPs. Once set up, the user experience is simple: provide ETH, receive xyzETH, and the underlying liquidity remains optimally deployed, while remaining within the DEX ecosystem. This approach creates passive yield opportunities for users, which retain all underlying liquidity within a single ecosystem, thus promoting sticky liquidity and broadening the addressable market.
A natural next step is to enable the permissionless creation of Autopools. This feature will allow users to express individual risk preferences and allows different participants, such as risk managers, to contribute specialized skills. The architecture of Autopilot also allows to develop solutions for other problem sets requiring optimization, such as e.g. point systems.
Important terms to know:
Autopilot
Comprised of a series of smart contracts, Autopilot is the primary system of Tokemak V2 that rebalances between a subset of given Autopool destinations. Autopilot introduces automated liquidity (autoLP) to DeFi, which connects liquidity previously isolated across different pools through autonomous LP rebalances.
Autopool
An ERC-4626 Tokenized Vault Standard pool within which user assets are deposited, which contains various different external destination contracts. Example destination contracts would be a Balancer or a Curve pool.
autoLP
Automated Liquidity Provision, used in reference to the network capabilities of assets deposited into Autopools and their corresponding yield bearing tokens
autoETH
autoETH is the yield-bearing Autopilot receipt token (also referred to as LAT) received after depositing ETH (or Wrapped ETH) into Autopilot's first Autopool, focused on LST-centric destinations.
autoLRT
autoLRT is a yield-bearing Autopilot receipt token for an LRT-based Autopool.
LP
Liquidity Provider, user who provides tokens as trading liquidity to exchanges. In the context of Autopilot, an LP is a participant that supplies ETH (or otherwise) to an Autopool.
LAT
Liquid Auto Tokens (LATs) are reward-bearing Autopool receipt tokens (e.g., autoETH). In essence, LATs are tokenized automated liquidity networks backed by LP positions. LATs enable a new kind of composability within DeFi, as a standalone token representing optimally deployed underlying liquidity.
LST
Liquid staking tokens (LST) are tokenized ownership claims on the ETH staked on the Consensus layer, such as stETH or rETH.
LRT
A liquid restaking token (LRT) is a token that gives users access to liquidity while participating in restaking.
Solver
The Solver is an off-chain component that proposes rebalance solutions to interchangeably convert assets and LP tokens, as well as LP token into other LP tokens. The rebalance solutions are proposed to the Strategy, once they satisfy the Strategy’s imposed on-chain constraints a rebalance takes place.
Strategy
The Strategy contract is responsible for determining if a given liquidity rebalance is in the best interest of an Autopool.
Rebalance
A deployment that occurs when: Idle assets move to a Destination, assets move from one Destination or another, or assets move from a Destination back to the idle state.
Destination
A liquidity pool within an Autopool set that may be the destination venue of a potential asset rebalance.
This guide contains all the information necessary to interact with all aspects of the Tokemak protocol.
Learn how to provide liquidity with Autopools and take advantage of Autopilot optimization.
This section provides instructions on how to stake TOKE as sTOKE and earn rewards.
This section will provide information on liquidity provision to TOKE/ETH liquidity pools on Curve and SushiSwap.
A list of available Autopools can be found in the "Autopools" section on tokemak.xyz. Select an Autopool in order to see detailed information and data associated with the specific Autopool, such as historical performance, underlying pools and assets etc. From here you are also able to interact with the pool:
Learn how to deposit into the Autopool and earnmore pool shares.
Stake your LAT receipt token for additional incentives.
Claim TOKE incentives and lock them for more autoETH pool shares.
Use the dashboard to track your portfolio and manage your Autopool positions and TOKE locks.
Browse to the "Autopools" section to select an Autopool and view additional details by clicking on it. Once you are ready, use the dialog box to deposit into the Autopool:
If your wallet is not connected to tokemak.xyz, or you need to connect to a different network for this Autopool, the main button of the dialog will prompt you to do so by clicking it.
Select the asset and amount you wish to deposit. You can deposit any asset, which will subsequently be swapped into the base asset of the Autopool (e.g. , ETH). You can select a specific slippage tolerance for the swap and deposit by clicking the cog icon.
Setting the "Auto-Stake" toggle to "on" will add the transactions to stake the LAT receipt token to the deposit transaction. If left in the "off" position, you will receive the receipt tokens into your wallet. These can always be staked at a later point.
Click "Deposit" in order to start the deposit process. Note that the first deposit of an asset will require an additional approval transaction.
Autopool deposits are not subject to lock-ups or cool-down periods, meaning you can withdraw your assets at any time. You can start the process by either clicking "Manage" in the Autopools of the "Portfolio" section, or by selecting the Autopool from the list in the "Autopools" section.
Select the "Withdraw" tab of the dialog.
Select the amount you wish to to withdraw and the asset you want to receive. You can withdraw as any asset; the system will make the swap for you. You can select a specific slippage tolerance for the withdrawal and swap by clicking the cog icon.
Click "Withdraw" to start the withdrawal process.
In case you have unstaked LATs that you wish to stake, navigate to the respective Autopool. If you are unsure about the Autopool or the status of your positions, you can browse your "Portfolio" section and check the Staking Status:
Staked: All the LATs associated with this Autopool position have been staked.
Partially Staked: LATs associated with this positon have partially been staked.
Unstaked: No LATs associated with this Autopool position have been staked.
Click on "Manage" and you will be taken to the Autopool where you can use the dialog to stake your LATs.
Select the "Stake" tab in the dialog.
Enter the amount you wish to stake and click "Stake." Note that the first staking transaction will require an additional approval transaction.
Confirm the transaction(s) in your wallet.
In order to withdraw from the Autopool or otherwise utilize your LAT tokens, you will need to unstake them. Either navigate to the Autopool via the 'Autopools' section or select it from your Portfolio view.
Select the "Unstake" tab in the dialog.
Enter the amount you wish to unstake and click "Unstake."
Confirm the transaction(s) in your wallet.
Autopool LPs who stake their LAT receipt tokens currently receive additional TOKE rewards, allocated every two weeks. A defined amount of TOKE is distributed pro rata among LPs, based on the total percentage of the total staked LAT they represent. The incentives split across the three Autopools currently open for deposits as follows:
50% to autoETH
30% to balETH
20% to autoLRT
The amount of rewards and the split across the different pools is subject to change.
Navigate to your Portfolio and locate the "Autopools" section. Under "Rewards," click "Claim" to initiate the claim process. During this process, you can choose either to compound your TOKE incentives to earn autoETH or to claim liquid TOKE directly to your wallet.
Compound Claim will lock your claimed TOKE for four weeks, earning additional autoETH receipt tokens. These tokens are the same as the LP receipt tokens you receive for depositing into the autoETH Autopool. You can learn more about TOKE locking here.
Basic Claim allows you to claim liquid TOKE directly to your wallet. Liquid TOKE can, for example, be used to provide liquidity to the TOKE/ETH pools on SushiSwap or Curve. Learn more about TOKE/ETH LP here.
All your positions can be found in the "Portfolio" section.
This is your total balance across all your Autopool positions.
Here you can see the allocation to DEXs and assets across all Autopools you have deposited into.
Here you can track and manage your individual positions.
Total Autopools Balance: Total balance across all Autopools.
Total Returns: Total cumulative return across all Autopools.
Average Daily Returns: Average return across all Autopools. High daily Composite Return Metric, 7-day moving average, 30-day moving average depending on Autopool age.
Average APR: Average APR across all Autopools. High daily Composite Return Metric, 7-day moving average, 30-day moving average depending on Autopool age.
Rewards: Current balance of additional earned rewards.
TVL: Total Value Locked of the Autopool.
Deposited: Cumulative deposits made into the Autopool.
Returns: Total cumulative return earned in the Autopool.
APR: APR of the Autopool. High daily Composite Return Metric, 7-day moving average, 30-day moving average depending on Autopool age.
You can see your stake status under the portfolio on the autopool section.
Staked. Your amount of LAT's stake is the same as the total amount of your position.
Partially Staked. Your amount of LAT's stake is no the total amount of your position.
Unstaked. You do not have staked tokens.
In your Portfolio, click on the 'Manage' button to go to the specific Autopool page, where you can manage your Autopool position:
Deposit / Withdrawal
Stake / Unstake
This section provides instructions on how to stake TOKE as sTOKE, allocate voting credits to Autopools and earn rewards.
Choose a staking duration of 1-4 months (4 to 16 weeks)
Credits are generated based on amount of TOKE staked as well as lock duration (boost multiplier)
Longer staking durations provide more credits through higher boost multipliers
Adding TOKE to existing stakes restarts the staking period for your entire balance
Stakes auto-renew for the same duration unless unstaking is initiated
Unstaking must be initiated during the final week of your staking period
If unstaking has been initiated, TOKE becomes available for withdrawal once the period ends
Initiating the unstaking does not affect the rewards earned during the final week of the staking period.
Allocate credits to activate Autopool Streams and earn rewards
Allocate to multiple Autopools simultaneously
Adjust allocations at any time without unstaking - this doesn't affect your staking period
Make sure you are staking on the correct chain for your target Autopool (e.g., TOKE on Base is required to allocate credits to the baseETH Autopool)
Learn how to stake TOKE and allocating your credits.
Learn how to unstake and withdrawing your TOKE
Learn how to claim your revenue streams TOKE rewards.
You can see your staking positions on the Portfolio or under each of the Revenue Markets.
In order to allocate credits and activate Reward Streams, you need to stake TOKE as sTOKE using the Staking Panel:
Visit the Staking page
Select a Network/chain (eg. Ethereum)
Click Manage on the Staking Lateral Panel
Enter the amount of TOKE you wish to stake
Choose a staking interval
Review your boost multiplier based on the selected duration
Proceed with the staking transaction
When adding more TOKE to an existing stake, the entire staked balance will restart its lock period with the newly selected duration. This means your total staked amount (existing + new) will begin a fresh lock period. The minimum staking period for the added TOKE is the currently selected staking duration.
Visit the Staking page
Select a Network (e.g. Ethereum)
Click "Manage" on the Allocation Panel
Use the plus symbol (+) to add or the minus symbol (-) to change the allocation, or you can enter allocation percentages that total 100%
When allocation ready, click “Save"
You can change your allocation of credits at any time – the changes go into effect with the next snapshot. Snapshots are taken once a week.
To withdraw your TOKE, you need to initiate the unstaking during the unstaking window (final week of your staking period). Once your staking period ends, your TOKE then becomes available for withdrawal.
Visit the Staking page during the final week of your staking period
Open the Staking Panel and select the Unstake tab
Enter the amount of sTOKE you wish to unstake
You continue to earn rewards while the unstaking is in process
Complete Withdrawal
Once your staking period ends, your TOKE becomes available
Return to the Staking Panel and select the Withdraw tab
Claim your available TOKE
Your staked TOKE (sTOKE) positions can be viewed in your dashboard in the Portfolio tab of the app.
From there, you can manage your sTOKE credit allocations (per network) by clicking on the manage button.
Rewards are claimable once a week from the Manage button within the Portfolio tab (in the Staking section).
Note: the first batch of staked TOKE rewards will become available Dec. 26th, 2024 - from there, rewards will be claimable weekly.
Providing liquidity to a TOKE/ETH liquidity pool means depositing both TOKE and ETH into the pool to facilitate trading between them on a decentralized exchange (DEX). In return, you earn a share of the trading fees and may receive additional incentives. Liquidity pools are available on SushiSwap and Curve v2. While liquidity is provided outside of tokemak.xyz, you can find links to the pools and basic info on these LP positions under the TOKE/ETH LP tab.e
Network Selection:
Ensure you select the correct network (Ethereum Mainnet). You can usually switch networks in the settings option of your wallet provider.
Using Ledger (Natively or with MetaMask):
Unlock your Ledger device and select the Ethereum app.
Make sure the 'Contract Data' setting is enabled in the Ethereum app settings.
Using Coinbase:
Use the scan QR option to connect.
To access directly from the Coinbase wallet, open the browser within the app and go to app.aave.com.
Using WalletConnect:
Use the scan QR code option to connect.
Using Rabby:
Use the scan QR code option to connect.
Make sure to select the Ethereum app and enable contract data. To enable contract data:
Connect and unlock your Ledger device.
Open the Ethereum application.
Press the right button to navigate to Settings.
Then press both buttons to validate.
In the Contract data settings, press both buttons to allow contract data in transactions.
The device displays Allowed.
Make sure you have enough ETH in your wallet to interact with the platform. You must have ETH in your wallet for the transaction costs-- without it you won't be able to interact. Depending on the network status, the cost of the transactions may vary. At least 0.05 ETH may be required to interact properly.
If you used the Tokemak protocol in the past you will not find your positions on the current V2, you will need to visit he Tokemak V1 protocol. You can find an interface to interact with V1 version of the Tokemak protocol here.
The following steps may solve your problems:
If you are using Brave browser, switch to another browser to see if the issues are coming from the browser. If it is related to Brave browser some helpful actions are:
Clearing cache data and cookies for the site
Hard refresh with control + F5 (or cmd + r)
Disable brave wallet (or the wallet not being used as default, for example metamask, dapper, etc.)or other extensions that might be interfering with proper connection with the wallet
If the site still won't load after taking the steps above, you will have to use the platform in another browser.
Make sure your internet connection is working and stable
Restart the browser and try to connect again
Try to hard refresh the site with control + F5
Check if there are any updates for your browser or wallet provider. If so, update it to the latest version.
In this situation make sure to not keep sending transactions, as every new transaction will be stuck pending the oldest transaction to be confirmed. You can get rid of the stuck transaction by speeding it up or cancelling it. Depending on the wallet you are using, you may have that option natively. For example, metamask or trust wallet have both the options to cancel or speed up transactions.
Below you can find a collection of technical information/docs and their respective contracts
At its simplest, this contract system is a set of a sub-systems that all revolve around, and reference each other through, a system registry. There are only a handful of user interactions that are mostly surfaced through a multicall router. Additionally, we have a few permissioned keeper-like processes that handle other parts of the system. Here we’ll run through general functionality and then dive deeper into each contract/system
The purpose of Autopilot is to continuously rebalance Autopool assets into the Destinations with the best return/risk profile. Earnings are auto-compounded for the users, reinvested into the Autopool, and then rebalanced out to begin earning. We’ll give an overview of how things work by looking at how the assets flow through the system.
Users must deposit assets into an Autopool for there to be assets to deploy. If this is a contract-to-contract interaction, this can happen directly in an Autopool. If this is a user interaction, through our UI, this will happen through our Router. The end-result is that the Autopool has idle assets sitting in it and the external party has Autopool shares in their wallet.
Once a sufficient number of assets are deposited, the Autopool, or more importantly the Strategy backing the Autopool, will begin to accept rebalance proposals from our Solver. When a proposal satisfies the constraints of the Strategy:
The Autopools underlying asset, WETH in this case, will be sent to the Solver specified in the proposal
The Solver will take those underlying assets and turn them into the LP tokens for the Destination specified in the proposal. This can involve swaps, liquidity provisioning, or w/e other means the Solver has to procure the LP tokens.
The Solver will send those LP tokens back to the Autopool
Once validating everything looks good with the Strategy, the Autopool deposit those LP tokens into the corresponding DestinationVault for that Destination.
The DestinationVault will do what it needs to with the LP tokens depending on the type of Destination it is. If its just a pool Destination then the LP tokens can stay there. If its a Curve+Convex Destination, then the DestinationVault will stake the tokens into Convex.
The DestinationVault mints the Autopool 1:1 shares of itself to represent the deposit
Each DestinationVault has its own Rewarder where its shares are virtually staked on the Autopools behalf.
At the end of the rebalance, the Autopool has less of its base asset, and some number of DestinationVault shares representing a claim on some LP tokens.
On a periodic basis, rewards from the Destinations will claimed and collected via a permissioned keeper process. This is most-likely, though not restricted to, incentive tokens through say Convex or Aura, for example.
These tokens all go to a central LiquidationRow contract where they can be liquidated to the base asset in bulk at a later time.
When that liquidation occurs, assets are sent back proportionately to the DestinationVaults that contributed to their balance. These assets are held in the DestinationVaults Rewarder where the Autopools earn them over a short period of time.
At least every 24 hours, each Autopool goes through a debt reporting where we re-value the LP tokens held by that Autopool. During that process, any available auto-compounded rewards are claimed and come into the Autopool as idle funds.
With sufficient idle assets in the Autopool, another rebalance can occur. There is no requirement that funds earned from a Destination must go back to that Destination.
The above outline focused on idle → LP rebalances but the rebalance step can occur for LP → LP rebalances as well. So long as the proposal results in a higher potential return (and satisfies other constraints) it can be executed.
The contracts were designed with a couple concepts in mind:
It is possible that Tokemak could run multiple, separate, instances of this system on the same chain and the majority of contracts would not be safe to share between the two.
Misconfigurations are a potential source of bugs and this is a highly configurable system. Any validations that can be performed during registration and setup, should.
To assist in enforcing these points, the system revolves around a SystemRegistry contract (src/SystemRegistry.sol
), and most contracts inherit from a SystemComponent (src/SystemComponent.sol
) contract that requires a reference to a SystemRegistry. These allow us to tie the various contracts together and provide a lookup point for the various contracts to talk to one another.
With the exception of the SystemRegistry contract which uses an “onlyOwner” setup for security (which will be granted to a multisig and eventually a Governor contract), all other contracts follow a RBAC security system.
AccessController
src/security/AccessController.sol
This is largely an OZ AccessControlEnumerable contract with the setup functions exposed, however, instead of each contract managing their own permissions, they all reference this one through the SecurityBase
contract.
Given the sensitive nature of this contract, it is one of the contracts that can never be changed or upgraded in the system.
SystemSecurity
src/security/SystemSecurity.sol
This contract allows us to coordinate operations across all Autopools in the system. This coordination falls into two areas:
Pausing
NAV operation coordination
Via the usage of this contract, we are able to pause all Autopool operations in the system. Autopools can still be paused locally or one-by-one, but this gives us a way pause all of them in one go.
Operations in an Autopool can be broken down into ones that can see nav/share go down, and ones that can’t. To ensure proper calculations, operations that SHOULD NOT see a nav/share decrease can never be executed within the context of those that can.
Operations that can see a decrease in nav/share:
Debt reporting - updateDebtReporting()
Rebalances - flashRebalance()
Operations that shouldn’t:
User balance management - deposit() / mint() / redeem() / withdraw()
This restrictions applies cross-Autopool as well. An updateDebtReporting()
call in one Autopool for example, blocks deposit()
in all Autopools during its execution.
Pausable
src/security/Pausable.sol
A near duplicate of the OZ contract by the same name. However, this one incorporates our SystemSecurity contract to support our global-pause behavior. It is used only by our Autopools.
The Stats System is responsible for making all required signals (e.g., staking yield, fee yield, incentive yield, etc) available on-chain. These signals are read by the Strategy to determine if a rebalance is in the best interest of its Autopool. A Calculator
is responsible for storing, augmenting, and cleaning data required to provide one of those signals. Let’s take an example Destination and see how it’s stats are built:
Curve osETH/rETH + Convex Staking
Stat calculators depend on each other to build the full picture of a Destination, with only the top-most calculator being referenced directly by the DestinationVault. In this case, the top-most calculator is the ConvexCalculator
. This calculator is an example of an Incentive calculator. LP tokens staked into Convex automatically earn CRV and CVX. This pool is also configured with SWISE and RPL tokens as extra rewards. And so, some annualized amount of CRV, CVX, SWISE, and RPL will be reported to the Strategy where it will calculate what the yield of those tokens are.
As a dependency, the ConvexCalculator
takes a reference to a calculator responsible for providing stats about the DEX pool itself, a CurveV1PoolNoRebasingStatsCalculator
(V1 calculators work for both Stableswap and Cryptoswap pools). This calculator provides the trading fee yield for the pool.
The last piece(s) are the stats about the LST tokens themselves, osETH and rETH. These calculators, OsethLSTCalculator
and RethLSTCalculator
, were provided to the CurveV1PoolNoRebasingStatsCalculator
as dependencies when it was created. These calculators provide stats such as the base yield and price-to-book value.
With all of these calculators each providing their own data to the overall picture, a Strategy can get an accurate reading of a Destinations return.
Incentive - Responsible for tracking the return of the incentives available when staking in Convex/Aura/Maverick/etc.
DEX - Responsible for tracking the trading fee yield of a given DEX pool
LST - Responsible for tracking the base yield and backing of an LST
A keeper network is used to periodically snapshot new data. Each calculator type defines the frequency and conditions under which a snapshot should be taken. Importantly, each calculator only stores the required information to provide its stats. If it needs to provide stats from another calculator, those are read at the time of the request to ensure that data is consistent.
The purpose of Autopilot is to continuously rebalance Autopool assets into the destinations with the best return/risk profile. However, the best risk/return profile is somewhat subjective, as such, each Autopool has an assigned Strategy
that is responsible for determining if a given rebalance (e.g., swap Pool A LP units for Pool B LP units) meets its requirements. For the LST vaults, there are a number of criteria that are considered in deciding if a rebalance is favorable, including:
Total Slippage - the absolute difference in the value of the in and out LP tokens. Priced using safe price oracles (previously audited).
Increase in expected return metric between the assets being swapped. Expected return is composed of (1) LST base yield, (2) DEX fee return, (3) incentive APR. Expected return metric is calculated as follows:
Swap Loss Offset Period - how long it takes for the incremental expected return to offset the immediate loss (swap cost). The Autopool will utilize an adaptive offset period that determines how strict or loose the offset period is. The LMP rebalance transactions (a.k.a pool/destination swaps) will occur only if the following condition is met:
where,
is the annualized gain in ETH expected to be earned as a result of this rebalance transaction.
are the new and old composite APRs for the destination involved in the swap/rebalance transaction.
is defined as period in days allowed for this rebalance transaction to recoup or recover the slippage loss. Default value is 28. At the minimum value of 7 days, approximately 525 bps of incremental APR will be needed to offset a swap cost of 10 bps. Similarly, a value of 60 days allows ~ 60 bps of incremental APR at 10 bps of swap cost.
is the loss in value in ETH units as a result of this transaction primarily driven by slippage, token swap fees, gas used to execute the rebalance operations.
Swap loss offset period determines how loose or strict the constraint to allowing a pool swap is. A large value relaxes the constraint and will allow many swap transactions to go through. In comparison, a value such as 7 days will require a large hurdle to be met before a destination pool swap transaction is allowed.
If the value of swap loss offset period is fixed at a high value, the Autopool system could exhibit increased turnover and experience increased swapping cost. The following describes the mechanism to adapt the swap loss offset period and tighten or loosen the pool swapping constraint should conditions warrant.
At every pool swap-out transaction, we determine the time elapsed since the last time we added to this pool. A pool swap-out transaction is a non trivial swap out i.e. swaps from WETH reserves (base asset of the Autopool) are not included. Let this time be $t$. Next, we define a constraint violation event as a pool swap out transaction where $t$ ≤ swap_cost_offset_period.
After 5 or greater constraint violation swaps within 10 swaps, the swap loss offset period is decreased by x (tighten step size) days until it reaches the minimum allowed value of 7.
After no swaps transactions occur for the period of y (constraint relax period) days, the swap loss offset period is increased by z (relax step size) day until it reaches the maximum allowed value of 60 days.
This is a test conducted on the NAV (per unit or token) of the Autopool. Swapping costs should be carefully monitored to provide positive value to the Autopool. The 30 followed by 60, 90 day test is meant to allow enough time for the Autopool to earn back the swap costs. Should a lot of swaps have recently occurred (i.e. frequent swaps is not a feature of the system but just happen to occur in clusters some times), looking back in the past far enough should result a positive NAV delta i.e. NAV per token should have increased over time. A variant of this test is a 30-60 NAV test.
The following steps are conducted in this test.
Aligned with some time reference (i.e. 30th of every month), record the NAV of the Autopool.
Calculate the delta with the NAV recorded 30 days in the past.
Calculate the delta with the NAV recorded 60 days in the past
Repeat with NAV recorded 90 days in the past.
If all of the three delta values are negative, pause pool swaps until
the NAV reaches the highest NAV recorded (of the 3 values - 30, 60, 90 days in the past)
90 days have lapsed since the test was conducted
After the pause, set the value of $swap\_cost\_offset\_period$ at the minimum value $swap\_cost\_offset\period{min}$
References:
verifyRebalance is called here by Autopool on rebalance to ensure it is a favorable rebalance.
At least every 24 hours, each Destination configured on the Autopool has its cached price information updated. This has the potential to lower the nav/share of the Autopool right at that moment. When the Autopool sees a profit during debt reporting, that profit is locked up for a period time, say 24 hours. This means any nav/share increase unlocks over that same time period. At the end of a call to debt reporting, AutopoolStrategy.navUpdate()
is called.
The valuation of tokens is core to the operation of this system. All token valuations are performed through the RootPriceOracle
and different approaches for pricing are used depending on the type of token (native or LP) and the intended usage of the price:
These are prices that are calculated/queried from off-chain sources. This includes sources such as Chainlink, Redstone, and Tellor. These are exposed through three calls on the RootPriceOracle
: getPriceInEth()
, getPriceInQuote()
, and one of the return values of getRangePriceLP()
These are mainly used for operations where we aren’t executing with the price at that moment. This can include pricing debt in the Autopools, calculating statistics, etc.
These are prices that are calculated/queried from primarily on-chain sources. These are always in reference to a specific pool that want to know the spot price of the tokens from. To calculate these values, a small amount of token is trial swapped through a pool to determine its execution price and then any fees are factored back in.
For requests that don’t have the requested quote token as one of the tokens in the pools, “safe” prices are used to complete the steps in the conversion.
These prices are exposed through getSpotPriceInEth()
and one of the return values of getRangePriceLP()
.
Spot prices are checked against some tolerance when used within the system to ensure they are safe to use. The spot price of the token must be within some bps of the safe price. These are used during rebalance execution to measure impact on pools we are operating against as well as one of the ends of the getRangePriceLP()
call.
These prices are exclusively used in the Autopools when debt reporting has gone stale. While this should never actually be an occurrence, should a pool enter this state, debt that is stale will be re-valued using this method of pricing. This will take the worst price (depending on the operation that could be the highest or the lowest) between the safe and spot prices of all the tokens that constitute the LP token, and value all the reserves that back that LP back at that single price. This is to ensure that any potential manipulation that could be occurring cannot negatively impact the Autopool.
The system-at-large will only ever interact with the RootPriceOracle. All specific implementations related to the method of pricing an asset are hidden behind here:
The majority of functions on the RootPriceOracle are not view functions even though they are performing “view” type operations. This is due to methods used for pricing. Since we use swaps to calculate prices, and we can’t count on every DEX to have a view operation to perform this, we have to keep the interface as payable.
The following is an example call flow for resolving a complex price. We will assume that the requested price is for the $ABC token in ETH. $ABC token has an $ABC/USD feed through Redstone:
The following is an example call flow for resolving the safe and spot price of an LP token. We will assume this is a Curve pool:
When there is a withdraw from an Autopool, a couple things can happen. If there are enough assets to cover the withdrawal sitting idle in the Autopool, then all of the assets come from there. However, if there is not, then we must pull from the market. Just retrieving the LP positions doesn’t help the user, we must provide them back their funds in the base asset of the Autopool. This is where the SwapRouter comes in.
The SwapRouter contains routes for all the tokens that make up the constituents of any LP token we support, back to the base asset of the Autopool. This is a list that will be kept up to date by the team to ensure users receive the best execution when exiting the pools.
The routes can be simple or complex. We can use the same pools we are in as Destinations or completely different pools should there be better execution.
Simple Example for TokenA → TokenD:
Swap TokenA → TokenD in Balancer TokenA/TokenD Pool
Complex Example for TokenA → TokenD
Swap TokenA → TokenB in Curve TokenA/TokenB Pool
Swap TokenB → TokenC in Uni V3 TokenB/TokenC Pool
Swap TokenC → TokenD in Balancer TokenC/TokenD Pool
The chaining of operations all happen at the SwapRouter level. The only thing an adapter needs to be able to do is to swap between two tokens and validate that a given configuration is supported in the specified pool. They are only callable by the Currently we support:
Balancer Pools
Curve StableSwap Pools
Curve CryptoSwap Pools
UniV3 Pools
Getting information generically about a given Curve pool can be a tricky task given the slight variations between their different types of pools. This is a task we need to perform in many different areas of the app and so this contract was built to assist in that.
Luckily, Curve provides a meta registry themselves that can perform this lookup. However, at the time of writing this, there is a type of pool that is not supported by their registry and that is their Stable-NG type pools. To get around this, the CurveResolver has a fallback method where it attempts to figure out the information based on the successful execution of various functions.
This approach currently works for the types of pools we are interested in supporting. Should new types of pools be introduced in the future, the approaches outlined may need to be re-evaluated.
This contract is an interface to be able push data or events to other chains. It is exposed to the rest of the system as a generic interface but currently relies entirely on Chainlinks CCIP. It is designed to support a couple core features:
Fan-out messaging. Given a sender and message type, send the provided data to one or many destination chains
Retries. The last message of a given sender+type can be re-sent to a destination. This serves a few purposes
Should CCIP ever be down and messages unable to be sent, we should be able to get the data off that we need when it comes back online
Our contract could be out of funds when the send is attempted. We need processes that send the message to continue without reverting, but we want to be able to send that message eventually
Seeding information when standing up the destination chain. Some messages have large delays between them being sent. This can make standing up dependent contracts on the destination difficult and time consuming. Being able to re-send the last message ensures we have the information we need as soon as we can.
Current usage is restricted to just the LST calculators through the LSTCalculatorBase. The stats related to LSTs are specific to their native chain.
accToke gives users the ability to stake their TOKE and earn rewards in WETH. This contract is largely based on https://docs.oeth.com/governance/ogv-staking.
Differences to call out
Rewards can accrue in the contract for a user and don’t actual claiming
Rewards are queued instead of being on an emissions schedule. Rewards will not be added in large amounts to ensure there can’t being meaningful gaming of, and spikes in, accRewardPerShaer
Generally accToke sits on the outside of the platform. It doesn’t have a integration into the Autopilot router. The exception to this is within the AutopoolMainRewarder. We optionally have the ability to configure that if TOKE is the token being rewarded, it can be staked for a period of time into AccToke upon claim.
The Autopilot Router is the main entry for users in the system. This is a multicall-type contract where the exposed functions are designed to be chained together to perform various operations. This can include but is not limited to:
Depositing into an Autopool and staking the tokens into a rewarder:
deposit(autoPool, router, amount, min)
approve(autoPool, rewarder, max)
stakeVaultToken(autoPool, max)
Migrating from one Autopool to another
withdrawVaultToken(autoPool, rewarder, amount, true)
selfPermit(autoPool, amount,….)
redeem(autoPool, router, amount, min)
approve(weth, autoPool2, max)
depositBalance(autoPool2, router, min)
stakeVaultToken(autoPool2, max)
The router also has the ability to swap tokens utilizing one of the AsyncSwappers configured in our system. Whether or not a swap can be utilized depends on the type of operation being performed. If we are able to know the exact number of input tokens upfront then it can be performed. Otherwise, we cannot.
Given the flexibility of the Router it is possible to leave funds in the contract should the order of operations be incorrect. Those funds can then be withdrawn by anyone. This is expected. The Router will be integrated into our front-end and only specific flows will be supported ensuring that all token balances are sent back to the user when appropriate.
Liquidation in Autopilot refers to the process of auto-compounding rewards from our various asset deployments. For efficiency reasons, LiquidationRow attempts to batch as much of the claiming and swapping process as possible. This is broken up into two processes:
Each DestinationVault is required to implement a collectRewards()
function which will claim and transfer any reward tokens back to the liquidator. The exact details of how a claim happen are not of a concern to the liquidator, it is only worried about being told how much of some token it has received. Call flow:
Both the process of claiming and liquidation can be gas intensive given how many DestinationVaults and reward tokens we may need to process in the system. Both of these processes are designed to be able to work on a subset of either the DestinationVaults or the tokens to combat this. The goal is batch as match of the work as possible for efficiency, though. So, during liquidation the balance of tokens across many DestinationVaults are compiled, swapped as a single operation, and the proceeds distributed back to the DestinationVaults according to the share they contributed. Call flow:
This process is one that is permissioned and run by Tokemak. To support the gas and fees required to perform this a fee can optionally be enabled against any liquidated funds.
Destination Vaults act as our proxy to the greater DeFi ecosystem. Their goal is to provide a common interface for us to deposit/withdraw LP tokens and earn yield. Each type of Destination has its own unique concrete DestinationVault implementation. Currently we support:
Balancer Pools
Balancer Pools with LP staked into Aura
Curve Pools with LP staked into Convex
Maverick Boosted Positions
Autopool’s will be the main actors interacting with a Destination Vault. Primarily this will come in the form of deposit and withdrawing LP tokens. The actions taken after a deposit aren’t much of a concern to the Autopool and can vary depending on the specific type of Destination. If this is a just a “Balancer Pool” type of Destination then the LP tokens will stay in the Destination Vault. If this is a Destination that say stakes into Aura, then that operation will happen upon deposit.
Withdrawing can come in two forms: as the LP units, or as the base asset. The LP unit can be withdrawn as part of a rebalance. During a user withdraw where we have to pull from the market, the LP units burned and the resulting tokens will be swapped into the base asset. All base assets in the system will be WETH at this time. Additional validations will be required to support additional base assets.
Depending on the type of Destination Vault, rewards may be due to us for holding or staking the LP units. The implementation of this can be hard coded to return nothing, or to interact with an external protocol. Resulting claimed tokens are sent to the caller of collectRewards()
.
These functions are intentionally left empty at this time.
DestinationVaults have very simple 1271 support. The exact usage of this is unknown at this time. However, much of the current and coming narrative around points and other various off-chain crediting systems present a unique problem for us when it comes to claiming these rewards. It is our hope that protocols will support this interface when it comes to claiming or at least we can prove ownership of transferrability of these rewards via this interface.
Autopools will be the main jumping off point for end-user interactions with the system (though technically this is the Router, these are the tokens the user will get back). Users will deposit and withdraw the base asset from here. Vaults are ERC 4626 + Permit compatible.
An Autopool is actually a pair of contracts. These contracts are:
The pool itself
A Convex-like, block height+rate style, Rewarder
The purpose of an Autopool is to represent a set of destinations that deposited assets may be deployed. It acts almost as an index. If an Autopool points to 5 destinations then your assets may be deployed to one or all of those destinations depending on how much those destinations are currently earning.
An Autopool should track it’s “base asset”. This is the asset that will be deposited and withdrawn from the pool. Any auto-compounding that happens will be in terms of the base asset, as well. However, it is expected that the Autopools associated Rewarder can emit any token(s).
Autopools support being able to recover tokens that are erroneously sent to it. However, we would not want the ability to be able to transfer out any tokens that are core to operation of the Autopool. This would include the base asset and any DestinationVault shares that it currently holds. Tokens that should not be transferred are called “tracked”.
At least every 24 hours, or whenever valuations deviate by a certain threshold, the value of the DestinationVault tokens that are held by the Autopool are re-valued. Deposits and withdraws from the Autopool are based on these cached values. Should this debt reporting result in an increase in value, shares will be minted to the Autopool to offset the increase. This is to ensure there isn’t a sharp increase in the nav/share of Autopool. Auto-compounded rewards are also incorporated during this time.
Two types of fees can be taken by the Autopool and they are taken during Debt Reporting.
Periodic Fee - This is a set fee annualized fee that is taken each Debt Reporting
Streaming Fee - This fee is taken on profit earned by the Autopool. Optionally, this fee can only be taken when profit exceeds previous values (the high watermark).
Should the high watermark be enabled and not be broken for a period of 60 days, it will start to decay until we are able to take fees again
Any locked profit will be burned to offset the dilution incurred by any minted fee shares
An Autopool tracks three valuations for any LP units it holds via a Destination Vault. These are the safe, spot, and mid point price of the LP tokens (see https://docs.tokemak.xyz/developer-docs/contracts-overview/autopool-eth-contracts-overview/autopilot-contracts-and-systems/pricing). These values are used for different purposes in the life cycle of assets in the Autopool:
Higher of safe and spot: Used during deposit to value the assets held by the Autopool
Lower of safe and spot: Used during withdraw to value the assets held by the Autopool
Mid point: Used for general reporting and fee calculations
To value shares for general purposes the standard ERC4626 convertToAssets(uint256)
should be used.
Using different valuations depending on the operation means that to find the maximum amount of assets one would receive during a redeem()
call we need something more than the standard convertToAssets(uint256)
. For this, we have an extension to the standard function:
Calculating the shares you'd receive on a deposit follows very closely to the previous example
Above we went through how the Autopool values the tokens it holds and how to calculate a max return value. However, there is another aspect to a redeem()
call that can affect the assets returned to the user. An Autopool holds a certain percentage of assets in idle to cover small withdraws. However, if an attempted withdraw needs more assets than sit in idle, the Autopool will start the redemption process by going to the market first. This entails removing liquidity from one or more destinations, and swapping out of non-WETH assets. These swaps can result in slippage and fee's taken in the liquidity pool being swapped through. The Autopool will also ensure that any recent price positive movements in the LP tokens being liquidated are captured. All of this is considered slippage that is passed on to the user performing the redeem()
.
To retrieve an accurate estimation of assets that would be returned one can use the previewRedeem()
call. However, it should be noted that this call deviates from the ERC4626 spec in that it is a nonpayable function instead of a view function. No state changes are made as a result of the call, but to provide the estimate state changes are necessary which are later reverted. This should not be called on-chain.
Due to this possible slippage, it is important to note that any call to redeem()
should be checked that an expected amount of assets were received and to revert if not.
Assets can be rebalanced between destinations according the rules of the Autopools configured strategy. Autopools support the ERC3156 flash loan interface and can grant our Solver access to funds to be able convert them into a more desirable Destinations LP token.
GIven that the creation of Autopools may vary widely depending on the type of Autopool being created (future looking), Autopools and their corresponding Factory are a 1:1 relationship. This differs from other factory+register+template relationships in our system:
Autopilot - Name of the overall system
Autopool - A 4626 vault that users deposit assets into
AutoPoolETH - A specific implementation of an AutoPool denominated in ETH/WETH
Destination - An external contract, or set of contracts, that we LP/stake user funds into
Examples
A Balancer pool
A Balancer pool with LP staked into Aura
A Curve pool with LP staked into Convex
DestinationVault - A contract that sits in front of a Destination in our system. These act has a proxy and give us a common interface to that Destination to perform our operations.
Solver - Contract that can turn assets into LP tokens, LP tokens into other LP tokens, or LP tokens into assets
Strategy - A contract that determines whether a Rebalance is in the best interest of an Autopool
Rebalance - The deployment of:
Idle funds to a Destination
Funds from one Destination to another Destination
Funds from one Destination back to Idle
Liquidation - The process of taking rewards and auto-compounding them into WETH
System Registry: 0x2218F90A98b0C070676f249EF44834686dAa4285
Access Controller: 0x37767cBfF88Cb623E9404e959560984F7D742dF6
System Security: 0x027a3359b803885261B140415873845f72238833
Autopool Registry: 0x7E5828a3A6Ae75426d739E798140513A2E2964E4
Destination Template Registry: 0xa698A94C0dCE389B862f58B08f618a981Ea99402
Destination Vault Registry: 0x3AaC1CE01127593CA0c7f87b1Aedb1E153e152aE
Destination Vault Factory: 0x37De6f9D23d26DfbCB6dbEE86Dc7ca538c0ff124
Swap Router: 0x6201523176dC66CCd249248b9c422Aac725eA3f2
Async Swapper Registry: 0x73526d80aC5Db9ccD2aa46436744c542eF9c0b75
Root Price Oracle: 0x61F8BE7FD721e80C0249829eaE6f0DAf21bc2CaC
Stats Calculator Registry: 0xaE6b250841fA7520AF843c776aA58E23060E2124
Stats Calculator Factory: 0x8198069F1709aDDC6A162c9433665776E5Bc917c
Curve Resolver: 0xC7c77B3a2C2641c6eE6c52bbD72EcfC86B53ba38
Incentive Pricing Stats: 0x8607bA6540AF378cbA64F4E3497FBb2d1385f862
Liquidation Row: 0xBf58810BB1946429830C1f12205331608c470ff5
Autopilot Router: 0x37dD409f5e98aB4f151F4259Ea0CC13e97e8aE21
MessageProxy: 0x20ea2F2ECf36bCb6Df086D923A120496DC616f76
EthPerTokenSender: 0xDd92511f1FbE5de911E22A0247Ba8c212D625A3d
dineroETH: 0x35911af1B570E26f668905595dEd133D01CD3E5a
AutopoolETH Template: 0xF90bB2BAa90B457A35c37c5A96De2720CE367281
AutopoolETH Factory: 0x7fEd74094B7010c6FB3010ed5EfC00772fD2ED1f
With Points Hook: 0x63139fe3848aC53E5b668e19Df1DD4e6f31428C8
Balancer Swapper: 0x780D5Bc2B1FFEfa1f5BBe1ab0C056C81774bA5F1
Curve V1 Swapper: 0x620fFcA1EF197f1CD9374BD31992b65A18E89Bc0
Curve V2 Swapper: 0xd3bF4ac5d54f262F977be28c761470ea0E612081
Uni V3 Swapper: 0x106A60958c8637C9DC850757D1Ed2AC11c73963d
wstETH Oracle: 0x31fec5a6C6bBF907144e6F81f60292BA7a5af883
eETH Oracle: 0xAA573a9bf7560870a925Ea1704C061546486dF81
ETH Pegged Oracle: 0xDEb361BAbf4C8277f0B2ee30914fb155b1A67DE3
Chainlink Oracle: 0x701F115a4d58a44d9e4e437d136DD9fA7b1B6C3f
Curve V1 Oracle: 0xaeD535d737e80597452d1f04D1b64b4f2Ab8A92b
Curve V2 Oracle: 0xD460a37880C35AACF4f01ea6748F1195899aD160
Balancer Meta Oracle: 0x4D37d799a44515c25e43cA6ec9E4fF7a0a2a34d9
Balancer Gyro Oracle: 0x4c70ef1DefFC14e8C0a3D5135EC8EbAfEFcC1c58
Balancer Composable Oracle: 0x7C19e64904ABA791dD653ECF7F355d65d7665a8b
Redstone Oracle: 0xe1aDb6967e1dBD5332d499dFA2f42377d1DA5913
Custom Set Oracle: 0x53ff9D648a8A1cf70c6B60ae26B93047cc24066f
PxETH Oracle: 0x3cC52170fDEA5C485db6d412b78ea40F27FFC629
Zero Oracle: 0x655fA98eA9BBcC6A2eB3F3c01F26929Fb3b8aa28
Points Hook: 0xA386067eB5F7Dc9b731fe1130745b0FB00c615C3
balETH Rate Provider: 0xd4580a56e715F14Ed9d340Ff30147d66230d44Ba
Aura Template: 0x594BAa7aD9230084261e40aDfCE95f2ed612898a
Balancer Comp Template: 0xF4b143f94eEF97FCB44EEa54C7927ce15f96e23c
Balancer Gyro Template: 0x4a3688fA864d42FAbaEa9E364266e81B50730e91
Balancer Meta Template: 0x084E65a576949a431F7E8e4C9154D1DDd7F25A0c
cbETH Template: 0x24d783e5ed8e4A507583e0C79ABf489051069AbB
Convex Template: 0xd1E668Ea38c68740eec6ebad453a082211C98709
Curve V1 No Rebasing Template: 0xd48A39a087FC4DD152867C5059c2667eC5Fa0E4d
Curve V1 Rebasing Locked Template: 0xCB29D488efcC308c07c3168c63d5E7AEDe4bC3aE
Curve V1 Rebasing Template: 0xf5C49C69ec7735B7baB85c591CA93c8124825ab4
Curve V2 No Rebasing Template: 0xD8eF136051014E89E9Ea6aE32C3cd224778125e4
eETH Template: 0xA87930c4e51Ce635065c9f5356A8578e94D4A71E
ETHx Template: 0x2757f5FB6f62eF4B41B5F6236D1E3a77e15B0C55
ezETH Template: 0xe3e73139d6B1a2Ce22C34897423AB56EE925b459
frxETH Template: 0xad6d0eCeE007145D76c7a9B9551Af560A718a223
osETH Template: 0x3cC4397EE396B49408AE12fd34c7c3B40F257B1b
Proxy Template: 0x8A26C73f5C4597e086254CB815403b98dc494E53
pxETH Template: 0x37C9B7Fc138A7489C307A7BC6bc1124e3d06296a
rETH Template: 0x038516cb9bbc0572c2d55896Ce75F31FaB90FAc1
rsETH LRT Template: 0x114ca0Dc51aBd118125F84d15F87E01e7dceFA86
rswETH LRT Template: 0xe861c6eB5376aDA41bCc238080439724FE15B90f
stETH LST Template: 0xaea78e6D52A55dAA7EeBeb25068637659E02CEE7
swETH Template: 0x7Cbbb3Db2FF81B1221d50c8f9b9072348dAc7408
cbETH Calculator: 0xaB78a570252dd06FDbC1C5C566E842e571d01E08
eETH Calculator: 0x4353e181C13f7E970f24016a0762C1af271350BA
ETHx Calculator: 0x6D3C5F6670ABe46901De4BD39036cF21d178334C
ezETH Calculator: 0xA84cc1d5aD1cDD5fAeb15Aa3f4aC5935D4b263D9
frxETH Calculator: 0x449A957490e24e4d915fD5Dcf25Dd5446E787590
osETH Calculator: 0xB5aa595C4FE3C297D65bdCDCc6FA48eF8725AEbB
pxETH Calculator: 0x9cB562083D29e027F21fAc4D8b66573deA972153
rETH Calculator: 0x9801098EE481ed6806C61A4dE259FBdDD5bb84a8
rsETH Calculator: 0x840A49a4b83E57718cf67c03D820C938A04FC210
rswETH Calculator: 0xeEdb3dD86F690a8c76006D606Db7951322B6741A
stETH Calculator: 0x66A466b838f981B39cF3B3E13E19AF5643Dbad0c
swETH Calculator: 0x60E98E2dAc20FAab84781076164290Cc31Ce3c9e
weETH Calculator: 0xDBFB637873D16DC5eFa43DB75Ff846934CaAA43f
wstETH Calculator: 0x24864cc03EFD84f9DF0e5F1D23aB69128325931E
Balancer rETH/WETH DEX: 0x66664bd801fF4edF8778BaE66ACF1De9C29a59a4
Balancer Aura rETH/WETH Incentive: 0x4Ead64090fe1D07B8a2306b2E4897386d5Eb43eA
Balancer WETH/osETH DEX: 0x0e2b7536Ecb785dF0fa43C6622Dd6b670cE39bE4
Balancer Aura WETH/osETH Incentive: 0x4e4eb584CCea7eCe23dA46245Daf07457BC48348
Balancer wstETH/WETH DEX: 0x4c4d65167B6c6b112480D2295A35300bEb3A1970
Balancer Aura wstETH/WETH Incentive: 0xacdc4a1CD67e7E9fe85F00EC29D5f07B1305829d
Balancer wstETH/WETH (Gyro) DEX: 0xa9B8E439D140E8f2644e1b4D98f3AABdb85702aB
Balancer Aura wstETH/WETH (Gyro) Incentive: 0x662e3fCFD4348Ef74fF88C88a6e9f4E4119b018B
Balancer wstETH/cbETH (Gyro) DEX: 0x943673e7996a5D2Ac2E945d0eABF1aa39913e9D2
Balancer Aura wstETH/cbETH (Gyro) Incentive: 0xB57e41106Fc06a5c0b6ACCc8cF8F72dD25fb6621
Balancer wstETH/ETHx DEX: 0x63B0aC87bDa3Ee6D13802A93FC13918Df5832aE9
Balancer Aura wstETH/ETHx Incentive: 0x041679ACb4088288178589c059543b56ce74ea07
Balancer pxETH/WETH DEX: 0x2dF5D9eF6D48A456bA5edC444dd5de7ad7AB0981
Balancer Aura pxETH/WETH Incentive: 0x5968662CCfb6792bB4a0E4f45Cf303b85fB2CC43
Balancer ezETH/WETH DEX: 0xADF54e42990f5B7d9f423D66D8652B53812Dd5A6
Balancer Aura ezETH/WETH Incentive: 0xD09bDE15c0BdD222EdcD79912c0636e451e59c71
Balancer rETH/weETH DEX: 0xa639d9C66dFa096d5A5a8Bf0BBb482a0c295193c
Balancer Aura rETH/weETH Incentive: 0x0f5d9c23D365c114D3feBAe6CB2edbB06b65ACAD
Balancer ezETH/weETH/rswETH DEX: 0xb5652e10eB7E93Eec7DFF8909A99FC3e6Aea6866
Balancer Aura ezETH/weETH/rswETH Incentive: 0x5Ac9DC1ceF6cBD9d5B8a604e2d3B7D93F59D7F40
Balancer rsETH/WETH DEX: 0xab0b5440E1bBdd3b6309Ea82364b2a49DB27F9a5
Balancer Aura rsETH/WETH Incentive: 0xddFD0A9a979182fA45E0024fDb101Dd8079D84B2
Balancer rsETH/ETHx DEX: 0x4E79861b9026109a9C5769631C182b3211BD70e0
Balancer Aura rsETH/ETHx Incentive: 0xA4349B50D2E64b24B4c35b2C24ad06177508f3A0
Curve osETH/rETH DEX: 0x145e12608C133C2b9062D10E33305d153aC41879
Curve Convex osETH/rETH Incentive: 0x74C3B0547BBCAc9584d072c6FBAc543267269Ab7
Curve ETH/ETHx DEX: 0xB8E7a5f5f5324AbD46f3Bd92c814C9B9719B8c2a
Curve Convex ETH/ETHx Incentive: 0x4bbFa11223315a21b51F37cF9dd3Bd6200332276
Curve WETH/rETH DEX: 0x94b58E201EAE7434B9FdCEa12E6B0B4fB26C7a69
Curve Convex WETH/rETH Incentive: 0x355f39596a4bc907A84dBF8F627C7CA2BA13dE91
Curve pxETH/stETH DEX: 0x54939860E3D185Cd983421ace105Ace79156E3C8
Curve Convex pxETH/stETH Incentive: 0x83B6945E843A22Bbda6bEAA06E88Bc1312301D7A
Curve WETH/pxETH DEX: 0xd545EE3Ba242E89FA45Caa68665898BAF4201004
Curve Convex WETH/pxETH Incentive: 0xF7370f9bF50985209Efe114096cD0177ba4Ba9d7
Curve WETH/frxETH DEX: 0xd6884a251E3D116344100e76917Df3C535eE6154
Curve Convex WETH/frxETH Incentive: 0xbfDF3A66a97Ae5e168FcE478bE0bE9804c163841
Curve WETH/weETHng DEX: 0x542A6b32e08980a8e9f4cd778805CFcB7A99f0Fa
Curve Convex WETH/weETHng Incentive: 0xF25b36c77e869b01477860a0EABc4f4Ff745EAC3
Balancer Aura rETH/WETH: 0x867991C7737Ccbb152aE5a7E6EDB05cA0670717E
Balancer Aura WETH/osETH: 0xFDa49984eb4eA4075b8b451032849347C633E94b
Balancer Aura wstETH/WETH: 0x5A4B544B9734930DDC587c9a2f093dC5058A4f4D
Balancer Aura wstETH/WETH (Gyro): 0xA1b9297525388BA3985413D982863f31e2A29d05
Balancer Aura wstETH/cbETH (Gyro): 0x92294A62D6D9F0FbE30Ba3B543edb1806561baD7
Balancer Aura wstETH/ETHx: 0xdfE3fA7027E84f59b266459C567278C79fe86f0C
Balancer Aura pxETH/WETH: 0xc4Eb861e7b66f593482a3D7E8adc314f6eEDA30B
Balancer Aura ezETH/WETH: 0x2f2CC1bf461413014741dD68481dB4a3686DAC3D
Balancer Aura rETH/weETH: 0x40219bBda953ca811d2D0168Dc806a96b84791d9
Balancer Aura ezETH/weETH/rswETH: 0xC9b5D82652a1C8214b0971A004983d0EEeDD751C
Balancer Aura rsETH/WETH: 0xf9779aEF9f77e78C857CB4A068c65CcBee25BAAc
Balancer Aura rsETH/ETHx: 0x60339056EC88996e41757E05a798310E46972cca
Curve osETH/rETH: 0x3F55eedDe51504E6Ed0ec30E8289b4Da11EdB7F9
Curve ETH/ETHx: 0x1Ea622fa030e4a78F4CC2f305dd3c08DA3F08573
Curve WETH/rETH: 0x2B08137BeABd2454AD3631DEB754F97C5c93eB78
Curve pxETH/stETH: 0xe4433D00Cf48BFE0C672d9949F2cd2c008bffC04
Curve WETH/pxETH: 0xbA1462f43c6f60ebD1C62735c94E428aD073E01A
Curve WETH/frxETH: 0x356c79Ab2B2cEFAB685004CE827146058A6c3e77
Curve WETH/weETHng: 0x5c6aeb9ef0d5BbA4E6691f381003503FD0D45126
System Registry: 0x18Dc926095A7A007C01Ef836683Fdef4c4371b4e
Access Controller: 0x20Dfa88e77D4eEB644F68C5752E7D1A3c21F27e8
Sequencer Checker: 0x564c39C2C5D120724DA31d1428773c1AEaD23535
System Security: 0x8C58aFf94D7fCB0e8daC43fC3713fcddac8b4006
Autopool Registry: 0x4fE7916A10B15DADEFc59D06AC81757112b1feCE
Destination Template Registry: 0xA1afC8aAF80dF8Ceb179E99Bb1A8Fb4D26095BA1
Destination Vault Registry: 0xBBBB6E844EEd5952B44C2063670093E27E21735f
Destination Vault Factory: 0xF34F7975Df6CB3dd95849A6c3b9343196AE9AbB6
Swap Router: 0x23783E62282ca68fd5C3Fb45Fc7AD01F21B85666
Async Swapper Registry: 0x3750d3315466A132eE7D10eBEe67f28e19577472
Root Price Oracle: 0xBCf67d1d643C53E9C2f84aCBd830A5EDC2661795
Stats Calculator Registry: 0x22dd2189728B40409476F4F80CA8f2f6BdB217D2
Stats Calculator Factory: 0xD82664A9B7A766B2c311B76C9e4384E8838B0a1C
Incentive Pricing Stats: 0xF28213d5cbc9f4cfB371599D25E232978848090d
Receiving Router: 0x32796698388fBC64281dEa9Fc4070DF80a12267E
Eth Per Token Store: 0x57831780565ae1526eD1cc2296C1143B3ad68Dfe
Autopilot Router: 0xa18B89225491230fDb1883cFbda65E7931606931
baseETH address: 0xAADf01DD90aE0A6Bb9Eb908294658037096E0404
Balancer Swapper: 0x4EfCc03e33470Cfef7B2666EfF67667F4173918B
Uni V3 Swapper: 0x0915f530eF9A52AAbAE9ac22DC2ecf5265Da6E71
Used for Aerodrome V3
Uni V3 L2 Swapper: 0xe4FeF293650442991C695A055f54D2A54868CA11
Aerodrome V2 Swapper: 0x2bb11C6407Bb9Dcbb5b776F789371DE5aaCA44a5
Incentive Harvester: 0x1BFCDfa2722c17959ACD1306dF1f0406A7d5BE5e
Destination Incentive Checker: 0xc3FF90869ecb5Ce2a4153EEF6a5dEe08f6598323
Liquidation Row: 0xE2F00bbC3E5ddeCfBD95e618CE36b49F38881d4f
Liquidation Executor: 0x0294D71B2C9b88D10F6d3286f5b25026147b2C8c
ETH Pegged Oracle: 0xe33703C5C1E1A5415B260F8C8eb8A2f49e746Aa9
Chainlink Oracle: 0xc7939c8337d01F32B669C6a16f20eD4a8E11641C
Balancer Composable Oracle: 0x859dDA370dDb15Bd59361CC756496E51b729399b
Redstone Oracle: 0x9AB4b68C3a3DdA0Cdf4Ec5C0ab9da2661Bdad1ee
Custom Set Oracle: 0x92C726da82389e0E9E81575960411BD6E8EAE3Ef
Aerodrome Oracle: 0x099A7e3Ff39024C3d1E87568b4edA59A938900f4
Zero Oracle: 0x01554657fa8c37161CAd0fdc090e6a26Aea1D14d
Custom Oracles: 0x8CD98E74A5ef4020bcd6D0397EFe42C34Afa5f23
Debt Reporting: 0xb2A71EF7649B95d7d5A3b8084e619C381Fa79413
Swap Routes: 0xf772Fcd65aCAE9814e6E4b228e554c1054aE2765
Incentive Harvester: 0xcA7d8b1F4398D11b302853d7fFd5D2b65073dE11
Reward Liquidator: 0xdEA337283410bAcC9418e13CbbB3b8F03dD2FBf7
Solver Exec: 0x91517Ba3793394008c461498de4899EEc2DB1658
Chainlink Incentive Prices Upkeep: 0x08b0617747ad7A839396a909876104E392713E4d
Chainlink Stats Upkeep: 0x30f285c7cB4304e82302ce06F24E285BD527c637
Bridged LST Template: 0x4Cb4b14128C868f35AFE9cac7c23cf821aA64F99
Aura Template: 0x9254926B61C205e8b64ED00681fE0b2de94B62f3
Balancer Comp Template: 0xBd0Fe980455e52e4D60c4EACBd6bC19A5cf29F6A
Aerodrome Incentive Template: 0xc8756b85C5e7C2AB0Aa675Fd606aa91E14E6EF01
Aerodrome Dex Template: 0xcef50Bf75ed027b8bAE5C49562B3f27B4f253985
rETH LST Calculator: 0xb5182945cAA19E3a9Fa35e70502fC3269d1fA9EA
cbETH LST Calculator: 0xB081af21468dEb33aaB9E37eAe6F5004Cc1cBDb0
wstETH LST Calculator: 0xA80b38Da84e7C7a094E6d0093DE374A00E892934
weETH LST Calculator: 0x58897eC6b7d7102BB24a29e99a14A6d9E517943e
wrsETH LST Calculator: 0xbaF2EE1C91cc8a00B386b14D65bdb4918604E1a7
Balancer WETH/rETH: 0x4fc45f7C2FEB07d5698cC12717f5b8D4f30002A9
Balancer Aura WETH/rETH Incentive: 0xb9e9818E551f676d6BE547Ed07e5875dC702B6E8
Balancer weETH/WETH: 0x800F535CE3F430B1F5475575d7D2Ff3A164820b3
Balancer Aura weETH/WETH Incentive: 0x7c4b58Eaa93005162Bc80285af2003517213c539
Aerodrome vAMM-weETH/WETH: 0xC7B711A5d1fCC19195E82E8c0D827e2E0bD2Bd10
Aerodrome vAMM-weETH/WETH Incentive: 0xd675D868c751A5B1F331Bcf5dCD1Fe7D45c2e76B
Aerodrome vAMM-WETH/wstETH: 0xd9B54d16a2cD15Abe6E8A9B8B596239A7f8042E3
Aerodrome vAMM-WETH/wstETH Incentive: 0xeaa026495601c47BFEb4bb6501c11Ba41a1ac028
Aerodrome vAMM-WETH/wrsETH: 0xE40523f7Bd5799b3C62921357b104f58C4A7c240
Aerodrome vAMM-WETH/wrsETH Incentive: 0x9813E3091278f41cD6B2686FF83255F97889F3e3
Aerodrome vAMM-cbETH/WETH: 0xb02cb15597E214b9A843CCFf9EEfe628C057184e
Aerodrome vAMM-cbETH/WETH Incentive: 0xe923f84CBbdCE6D12C7987511C0B2C122f425318
Balancer Gyro cbETH/wstETH: 0x9d95E1fEcd950110Ab1126Cc6ed3C87C61e39e33
Balancer Gyro cbETH/wstETH Incentive: 0xC5A9170d151Cfea07489bd9dB5ECf20B5b7654D4
Autopool Template: 0x2ab4a3A8224726cBAA91d6b04D212979F06efdF9
AutopoolETH Factory: 0x78A7c45E3cC7B9567b4803AEAF9b33bC8c898451
Strategy Template (No Hook): 0xb111C5F02A04E1Bba747b6FF622F73Cf2eC2D9B0
Balancer Aura: 0x2A7a163168682f58a5294089b7EB87A65d92b1ed
Aerodrome: 0xDBD14969B9313E5BFdfeD2C7A29e813E6f02C627
Bal Gyro Aura: 0xee5E7575Df9db1446f9D601769F448Bb4a10F3f7
Balancer Aura rETH/WETH: 0xa6EFB95B7393cB419B48A933273F49b6bb48dd5D
Balancer Aura weETH/WETH: 0xb3723E69D6e4553239d7dAf514bF8ff7998500E0
Aerodrome vAMM-weETH/WETH: 0x945a4f719018edBa445ca67bDa43663C815835Ad
Aerodrome vAMM-WETH/wstETH: 0x58C2233399B85b53C5506f78eAaae9b0DBA1eD3E
Aerodrome vAMM-WETH/wrsETH: 0xA94031Ed4b316B043464FDd5482877F42A39845a
Aerodrome vAMM-cbETH/WETH: 0xd18db4dD6aF6A7536aD7F863C136463681e0CdAD
Balancer Aura Gyro cbETH/wstETH: 0xBd137c56f3116E5c36753037a784FF844F84F59c
Various Security Audits Below
Our current bug bounty program can be found on Remedy: https://r.xyz/bug-bounty/programs/tokemak
autoUSD Audit - March 2025
Autopilot Full System Audit - May 2024
Autopilot Full System Follow Up - July 2024
LMPStrategy Security Assessment & Formal Verification Report - Jan/March 2024
Crowd Competition Smart Contract Audit, February - March 2024
Autopilot (Autopools) Contracts - Preliminary Smart Contract Audit - Sept 2023
Autopilot Pricing Contracts - Formal Verification Report - Sept 2023
Autopilot Contracts - Crowd Competition - Sept 2023
accTOKE Contract - Nov 2022
This report describes the specification and verification of the Tokemak v2 LMPStrategy contract using the Certora Prover and manual code review findings. The work was undertaken from January 2nd 2023
Learn how to optimize withdrawals to limit slippage.
Autopools allow you to deposit and withdraw in the same asset, the base asset,and to do so on-demand. This means when your withdrawal is large enough to require pulling assets from the underlying LP markets you may incur slippage from swapping back into the Autopool's base asset.
By default, the Autopilot system is configured to be able to swap out of these assets all on-chain with no additional work or information needed. However the quality of trade-execution back into the base asset is limited by the liquidity present in the configured routes that are on-chain. We'll outline here how to provide your own routes to optimize withdrawal execution and to set limit slippage controls.
The first step in providing your own routes is to make a rough estimate as to the tokens and amounts that the Autopool will attempt to swap out of. For a TL;DR version, we have provided a package that will give this information for an Autopool and share amount: https://www.npmjs.com/package/@tokemak/autopilot-swap-route-calc If you're able to use the package then you can skip the following section. However for those that wish to calculate these tokens manually, read on.
If you wish to calculate these values on your own, you should inspect the logic that is performed during the redeem()
operation on the Autopool: https://github.com/Tokemak/v2-core-pub/blob/main/src/vault/AutopoolETH.sol#L357
Some parts to highlight:
One cannot receive more than assets than the shares valued using withdrawal pricing
If there are enough assets in idle to cover the value of the shares, no swaps are needed
The destinations used to pull assets are picked from the withdrawal queue on the Autopool: `getWithdrawalQueue()`
As with calculating the amounts to swap, we have an interface to get optimal swap executions as well. This is via an API that under the hood utilizes DEX aggregators such as 0x and Bebop. To call:
Where the tokensToLiquidate
is the output from the package @tokemak/autopilot-swap-route-calc package above. systemName
stays "gen3".
The results
from the API output is what will be later passed into our Router for execution:
It's possible to use your own contracts as well during the swapping and redemption process instead our API and swapper contracts. To illustrate what would need to be done lets look at the execution flow.
During the redeem()
process, our swapper contracts are engaged 0..n times based on the amount of shares being redeemed and the Destinations/markets we need to pull from to satisfy. For example:
User is redeeming 100 Autopool shares worth 102 ETH (idle only has 5 ETH so it can't cover)
The Autopool has 50 ETH worth of assets deployed to the first Destination in the withdrawal queue and 200 ETH worth of assets deployed to the second Destination in the withdrawal queue.
The first Destination is a wstETH/WETH and the second a pxETH/rETH
Lets assume all assets are priced at 1 ETH. We would expect our swapper contracts to be engaged 3 times:
Swap 25 wstETH into WETH
This swaps to WETH because the asset() on the Autopool is WETH
Since the second token in this Destination is already WETH, it is skipped for swapping
Swap 26 pxETH into WETH
Swap 26 rETH into WETH
We exhausted the 50 ETH worth of assets from the first Destination and then moved to the second to get the remainder
Using the output from our API as an example you'd construct an array of the fromToken,toToken,target,data
for each of three tokens above, wstETH, pxETH, and rETH:
target
is the contract you want us to call
data
is the call data you'd want us to use to call your target
Before your function is called the assets to be swapped will be transferred to the target
Before the execution of the function ends, the contract should transfer the new assets back to the msg.sender.
Redemption with custom swap routes is only possible through our Autopilot Router multicall contract (see Contract Addresses). There are multiple ways to construct the call but ultimately you are attempting give the Router access to your tokens (through approvals, sending, or having the Router pull them) and calling redeemWithRoutes()
Main Site
X - Main
X - Backup (Old)
Tokemak Blog
Discord
Radio (community built)