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...
High level documentation of smart contracts
E721 farms include all the farms built for pools in which the liquidity provider has an NFT (ERC721) position.
Loading...
Loading...
Loading...
Loading...
These contracts are base for all the other contracts and they have the common logic for functionalities like deposit, withdraw, createFarm, etc.
Loading...
Loading...
Loading...
Loading...
Features contracts can be considered as plugins, which are used in farms only where they are needed.
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
To mint new USDs, minters only need eligible collateral. Currently, the protocol is accepting USDC.e, USDC, USDC.e, Frax, DAI, USDT and LUSD as collateral and more tokens might be added to this list in the future. However, USDs tokens are fungible and redeemable in the same way, independent of their underlying minting collateral. It acts as an IOU on the pooled collateral.
The protocol will mint 1 USDs by collecting 1 USD worth of collateral.
Collateral tokens required = No. of USDs tokens minted/Min (Price of collateral in USD, 1 USD)
When a collateral token is worth less than 1 dollar, it will be treated with its actual market price. However, when it is worth more than 1 dollar, it will be treated as 1 dollar. Hence, USDs will always be fully collateralized or over-collateralized.
Mint fees are subject to Sperax DAO approval.
Redeeming 1 USDs at the protocol level gives the user back any one unit of collateral (maximum 1 unit of collateral) after deducting the redemption fee. Redeemers can choose from the list of eligible collaterals that they want to receive. A portion of USDs redeemed is collected as a redemption fee by the protocol.
The protocol will redeem 1 USDs following this simple equation:
Fee = x% of USDs amount redeemed. 'x' depends on the selected collateral.
Collateral tokens redeemed = (1-x)% * (No. of USDs redeemed)
When a collateral token is worth more than 1 dollar, it will be treated with its actual market price. However, when it is worth less than 1 dollar, it will be treated as 1 dollar. Hence, USDs will always be fully collateralized or over-collateralized.
The aggregate collateral ratio (or CR = Total Value Locked/USDs Circulating Supply) should be close to 100% as USDs are backed by stablecoins and collateral is expected to hold their price even in situations of market volatility. However, in an extreme situation if the value of locked collateral changes and the collateral ratio drops by more than 10%, the protocol will be paused manually. Redemptions will begin based on governance or if the collateral ratio increases. To cover any gaps in collateralization SPA reserves from Treasury may be used by the protocol.
Redemption fees are subject to Sperax DAO approval.
While minting USDs, if the price of the collateral token is more than 1 USD, then USDs will treat the price of the collateral as 1 USD and will only mint 1 USDs per collateral token deposited. But if the price of the collateral is less than 1 USD then more units of the collateral will be required to mint a unit of USDs. In that case minters would need to provide 1 USD worth of collateral to mint 1 USDs. If the price of the collateral has dropped below 0.97 cents then users would not be able to use that collateral to mint USDs. While redeeming users would always receive one unit of any collateral token of their choice for one unit of USDs.
Fees will be calculated and configurable based on the current state of the protocol’s collateral composition. Anyone would be able to call a function that updates the fee parameters. When a collateral would exceed the desired collateral composition the fee for that collateral would increase and its redemption fee would decrease. Similarly when the amount of collateral in the protocol is less than the desired amount, the mint fee for that collateral will decrease and the redemption fee would increase. Initially all collaterals except for USDC will be set to have a desired collateral composition of 20% and the base fee will be set to 0.05%. Any collateral having a composition of greater than the desired collateral composition cap will have a mint fee of greater than the base fee. The exact applicable fee on a collateral will vary and can be queried via a view function in the contract.
x: Current collateral value in number of tokens
Ca: (Desired collateral composition in % x Total Collateral in the Vault)
Total collateral in vault = Total USDs supply
Base mint and redeem fee (f base): Base fee for mint and redemption which will be discounted/increased dynamically based on the collaterals composition.
Now users can redeem their choice of collateral from any yield strategy, instead of relying on a preset default mechanism. Strategies are a set of smart contracts that control the depositing and withdrawal of collaterals from various other DeFi protocols like Aave, Compound, Curve etc.. The slippage that occurs is still transferred back to the redeemers but since redeemers have a choice, they could calculate and manage their own slippage. Withdrawing from single sided strategies like Aave and compound could have significantly less slippage as compared to withdrawing from complex liquidity pool strategies like Curve.
Auto-yield is distributed after a user redeems and before a user mints. So minters and redeemers should check if there’s an eligible auto-yield.
How does USDs keep the peg?
Minting 1 USDs - If a collateral token is worth less than $1, it will be treated with its actual market price. However, if it is worth more than 1 dollar, it will be treated as $1.
Redeeming 1 USDs - If a collateral token is worth more than $1, it will be treated with its actual market price. However, if it is worth less than 1 dollar, it will be treated as 1 units of collateral at its market price.
Hence, USDs will always be fully collateralized or over-collateralized. For more information on how mint and redeem functions work check outMinting and Redeeming
The protocol collects a redemption fee whenever USDs is redeemed. This fee is passed on to the SPA stakers. Redemption fee is levied so that protocol does not work like a free token swap instrument. The fee is static for each collateral token but can be upgraded through governance by the community. It is a percentage of the transaction value.
Mint Fee = 0
Redemption Fee = x% of the amount of USDs redeemed.
x depends on the selected collateral. Check the current redemption fee for the USDs in app.sperax.io
If the collateral being used to mint USDs has de-pegged by 2% or more to the downside then protocol will stop minting USDs using that collateral.
As more people use USDs, the yield rate will serve as a second-layer protection from a high selling pressure, further empowering a mass adoption in various use cases including payment, derivatives, and portfolio construction. For more information on how auto-yield works check out Auto Yield
When sufficient collateral is not available, USDs redeemers would get $1 worth of collateral in the form of SPA tokens. This would be the collateral of last resort.
Collateral types to mint/ redeem USDs.
Desired collateral composition, oracle used for price feed of the collateral, base Mint Fee, base Redemption Fee and price floor for each collateral type. Updating the price floor for collateral used to mint USDs. Setting the price floors for each collateral will allow the protocol to remain solvent when collaterals depeg. The protocol will not mint USDs with the collateral when the price of the collateral falls below the price floor.
Yield generation strategies for each collateral type. For example, adding new delta-neutral yield farming strategies based on other decentralized exchanges.
Harvesting incentive.
The USDs dripping rate from the dripper contract.
Minimum and maximum APR for distribution of Auto-Yield.
Harvesting or claiming all kinds of yield tokens from the yield generation strategies. The harvester will be incentivized with a portion of the yield-farmed tokens.
Purchase harvested yield tokens for market price. We will use the respective oracles for the yield tokens to determine the market price. This experience will be similar to the currently implemented buyback contract.
Distributing the auto-yield to all addresses eligible to collect it. Rebase will also be triggered when someone Mints or Redeems.
High level documentation of smart contracts
A yield automating stablecoin on the Arbitrum network
The highlights of this protocol:
Auto-yield - Users holding USDs in their wallets automatically earn organic yield. No staking is required by the end user. Users do not need to spend gas calling the smart contract to claim their yield.
Layer 2 native — Cheaper transaction fees on Arbitrum make this protocol retail investor-friendly
Fully Backed Model - USDs is 100% backed by a diversified basket of whitelisted crypto assets (stablecoins)
USDs automates the process of earning yield on stablecoins. Yield is generated organically by sending collateral to audited decentralized finance protocols. 50% of yield generated on collateral is used to pay USDs holders Auto-Yield. USDs Auto-yield rate is adjustable and depends on the actual yield generated by the collaterals. Any yield generated beyond the max Auto-yield rate will be stored in Auto-yield reserves. This novel passive income strategy does not require any action from the user. Users can just hold USDs and see wallet balance grow, auto-compounding the yield in the process.
SPA is the governance and value accrual token of the Sperax ecosystem. SPA holders can stake SPA tokens to receive veSPA. veSPA holders are decision makers of the protocol. They will earn staking rewards and manage the protocol revenue via voting power in Sperax governance. Off-chain governance is live and community (veSPA holders) can control parameters of USDs protocol, yield strategies, eligible collateral, new product features, etc. On-chain governance will be launched soon making veSPA holders true owners of the Sperax ecosystem.
USDs is a which generates auto-yield natively. Currently, USDs is live on Arbitrum, the largest Layer-2 Ecosystem of Ethereum. It has achieved $20M TVL in the first 2 months since launch. Eventually, Sperax will build a system of interoperability so that USDs will be natively deployed to all major blockchain platforms.
The growth of the space has spearheaded the adoption of stablecoins. However, existing stablecoins like fiat-backed stablecoins (USDT, USDC) are centralized, CDP based stablecoins (DAI) have a difficult time scaling and algo-stablecoins (like Basis, Terra) only maintain stability during bull markets. USDs has combined the best of existing stablecoin designs by featuring a 100% backed model like the CDP stablecoins, but adds the scalability benefits of fiat backed stablecoins. An on-chain, redemption based design makes USDs highly scalable, trustless and decentralized.
This technical document is about the upgrade to USDs-v2. It details the changes made to enhance the protocol's decentralization, transparency, security, and scalability. The document covers new features and functionalities.
Externally owned accounts (EOAs) holding USDs were always eligible for the Auto-yield feature, but smart contract / smart wallets were not.
Sperax has introduced a new function: now smart accounts (or smart wallets) can call to opt in for auto rebase in USDs contract and to get Auto-yield.
An owners of a smart contract / smart wallet can opt in for rebase in USDs contract. The users will not need to claim (or send out any transactions to claim) the interest earned.
This is how to opt in your smart contract / smart wallet for rebase in USDs:
Go to Arbiscan and search for USDs. Verify the correct USDs contract address: 0xD74f5255D557944cf7Dd0E45FF521520002D5748
Go to the Token contract. ensure it is Sperax USD (USDs) deployed by Sperax Deployer 0x42d2f9f84EeB86574aA4E9FCccfD74066d809600
Click on the contract and make sure your account is connected (Metamask, Gnosis Safe, or any other smart account).
Go to “Write as Proxy”.
Connect your wallet (choose WalletConnect, Coinbase Wallet, or any other wallet).
Once connected, you will see two functions with the same name: rebaseOptIn
You don’t have to call the first function because it’s an owner-only function (can be called only by the USDs owner).
Instead, click the second function rebaseOptIn
. This allows you to opt in for rebase for your own account (your smart contract account).
Confirm the transaction, and your smart account will be opted in for auto rebase.
That’s it. Your smart account / smart wallet is eligible for auto-yield!
USDs earns organic yield for holders and the yield is paid out in USDs approx. every 7 days
USDs stands out from other stablecoins thanks to its inflation fighting Auto-Yield feature. USDs is novel in the stablecoin ecosystem, because it requires no action by the user. Users do not need to stake USDs nor spend gas to claim their yield. One simply holds USDs, and their wallet balance will grow.
The collateral received for minting USDs is deployed in other audited, defi projects to generate organic yield. USDs collateral earns yield in the form of reward tokens and swapping fees from the pools. This yield is shared between USDs holders and SPA stakers (The split is 50% for Auto-Yield and 50% for SPA buyback and burns. This share can be changed through governance).
Gas free yield: 50% of yield generated on USDs collateral is used to mint USDs. This USDs is distributed to anyone who holds USDs in their wallet.
The actual yield generated depends on the yield rate of the strategies where collateral is deployed. However, the protocol will try to maintain a target yield of 11% APY (maximum) so that USDs holders get stable returns irrespective of market conditions. Any yield generated over 11% is stored in the protocol to help fund the APY for lean periods when actual yield generated is less than 11%.
Different yield generation strategies are proposed by the community/team and evaluated by the community based on their yield generation potential, risk profile etc. Community then votes to choose pools/farms where collateral will be deployed. Following strategies are being used for yield generation. We will keep updating this list to include newer strategies approved by the community.
Strategy list as per SIP-55:
USDC:
Compound (USDC)
Aave (USDC)
Maximum cap of 75% of total USDC collateral for each strategy.
USDC.e:
Compound (USDC.e)
Stargate (Stargate-LP USDC.e)
Aave (USDC.e)
Curve (FRAX-USDC.E)
Maximum cap of 50% of total USDC.e collateral for each strategy.
DAI:
Aave (DAI)
Radiant V2 (DAI)
Maximum cap of 75% of total DAI collateral for each strategy.
USDT:
Aave (USDT)
Stargate (Stargate-LP USDT)
Maximum cap of 75% of total USDT collateral for each strategy.
FRAX:
Frax (Curve-LP FRAX/VST)
Curve (FRAX-USDC.E)
Maximum cap of 75% of total FRAX collateral for each strategy.
LUSD:
Camelot (LUSD-USDC V2 Pool)
Aave (LUSD).
Maximum cap of 75% of total LUSD collateral for each strategy.
Old strategies that are not in use / deprecated:
Curve | Curve-LP USDC/USDT [Not in use]
Saddle | Saddle-LP FRAX/USDC [Saddle sunset] Frax | Curve-LP FRAX/VST [Vesta sunset]
USDs held in EOA wallets, i.e. non-contract addresses, will receive auto-yield on a regular basis. For now, USDs that are deployed by users to yield-earning strategies within the Sperax suite of yield farms will not receive auto-yield.
By default, smart contracts holding USDs are not included in the yield distribution process and do not earn any yield. A smart contract’s USDs balance remains the same after an auto-yield distribution event. However, based on community’s feedback and once approved by veSPA holders via Snapshot voting, the Sperax team can whitelist specific smart contracts to be part of auto-yield, and provide technical support to determine whether a protocol is compatible with the auto-yield feature of USDs.
USDs follows the ERC20 token standard. A wallet holding USDs should expect its USDs balance to increase automatically over time. This increase is triggered by a distribution event that happens on average every 7 days. The earned USDs are not explicitly transferred into the user’s wallet, instead a global parameter is changed to update the holder's balance.
Unlike most ERC20, where the token contract directly stores the amount of tokens each wallet holds, USDs’ token contract has a shared state variable creditPerToken, and the contract stores each wallet’s credit. A wallet’s balance = credit / creditPerToken.
When yield is generated:
The yield is swapped for USDs in the open market
The USDs from step (1) is burned
The value of creditPerToken is *decreased globally and therefore every wallet’s balance increases (since every wallet’s credit is unchanged during this process)
*: creditPerToken is decreased according to the amount of USDs burnt in step (2) such that total supply of USDs remains unchanged after steps (2) and (3)
The circulating supply of USDs remains unchanged through this process as the USDs that are bought from the market are burnt and then the USDs balance of the holders increase proportionally. As a result, a user can expect its USDs balance to increase automatically over time without any additional USDs explicitly being transferred to the user’s wallet.
Yield is distributed approximately every 7 days. The exact distribution time is determined in a quasi-random way. We have decided on this randomised distribution time to prevent users from timing their USDs minting and redeeming with yield distribution events. Huge spike in minting or redeeming around the time of yield distribution can put strain on the peg and this randomisation works as a defence mechanism for maintaining peg.
Inherits: Ownable, IOracle
Author: Sperax Foundation
Communicates with different price feeds to get the price
Store price feed data for tokens.
Add/Update price feed for _token
Have to be extra cautious while updating the price feed.
Parameters
Remove an existing price feed for _token
.
Parameters
Gets the price feed for _token
.
Function reverts if the price feed does not exists.
Parameters
Returns
Validates if price feed exists for a _token
Function reverts if price feed not set.
Parameters
Returns
Gets the price feed for a _token
given the feed data.
Parameters
Returns
Responsible for following actions on USDs:
Mint USDs token
Redeem USDs token
Carry out rebase for USDs token
Allocate collateral to strategies
Withdraw collateral from strategies ?
Inherits: Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable
Author: Sperax Foundation
This contract enables users to mint and redeem USDs with allowed collaterals.
It also allocates collateral to strategies based on the Collateral Manager contract.
Updates the address receiving fee.
Parameters
Updates the address receiving yields from strategies.
Parameters
Updates the address having the configuration for collaterals.
Parameters
Updates the address having the configuration for rebases.
Parameters
Updates the fee calculator library.
Parameters
Updates the price oracle address.
Parameters
Allocates _amount
of _collateral
to _strategy
.
Parameters
Mint USDs by depositing collateral.
Parameters
Mint USDs by depositing collateral (backward compatibility).
This function is for backward compatibility.
Parameters
Redeem USDs for _collateral
.
In case where there is not sufficient collateral available in the vault, the collateral is withdrawn from the default strategy configured for the collateral.
Parameters
Redeem USDs for _collateral
from a specific strategy.
Parameters
Get the expected redeem result.
Parameters
Returns
Get the expected redeem result from a specific strategy.
Parameters
Returns
Rebase USDs to share earned yield with the USDs holders.
If Rebase manager returns a non-zero value, it calls the rebase function on the USDs contract.
Get the expected mint result (USDs amount, fee).
Parameters
Returns
Mint USDs by depositing collateral.
Mints USDs by locking collateral based on user input, ensuring a minimum expected minted amount is met.
If the minimum expected amount is not met, the transaction will revert.
Fee is collected, and collateral is transferred accordingly.
A rebase operation is triggered after minting.
Parameters
Redeem USDs for collateral.
Redeems USDs for collateral, ensuring a minimum expected collateral amount is met.
If the minimum expected collateral amount is not met, the transaction will revert.
Fee is collected, collateral is transferred, and a rebase operation is triggered.
Parameters
Get the expected redeem result.
Calculates the expected results of a redemption, including collateral amount, fees, and strategy-specific details.
Ensures that the redemption is allowed for the specified collateral.
Calculates fees, burn amounts, and collateral amounts based on prices and conversion factors.
Determines if collateral needs to be withdrawn from a strategy, and if so, checks the availability of collateral in the strategy.
Parameters
Returns
_token
address
address of the desired token.
_source
address
price feed source.
_data
bytes
call data for fetching the price feed.
_token
address
address of the token.
_token
address
address of the desired token.
PriceData
(uint256 price, uint256 precision).
_token
address
address of the desired token.
bool
bool if price feed exists.
_token
address
address of the desired token.
_source
address
price feed source.
_msgData
bytes
call data for fetching feed.
priceData
PriceData
(uint256 price, uint256 precision).
_feeVault
address
New desired SPABuyback address.
_yieldReceiver
address
New desired yield receiver address.
_collateralManager
address
New desired collateral manager address.
_rebaseManager
address
New desired rebase manager address.
_feeCalculator
address
New desired fee calculator address.
_oracle
address
New desired oracle address.
_collateral
address
Address of the desired collateral.
_strategy
address
Address of the desired strategy.
_amount
uint256
Amount of collateral to be allocated.
_collateral
address
Address of the collateral.
_collateralAmt
uint256
Amount of collateral to mint USDs with.
_minUSDSAmt
uint256
Minimum expected amount of USDs to be minted.
_deadline
uint256
Expiry time of the transaction.
_collateral
address
Address of the collateral.
_collateralAmt
uint256
Amount of collateral to mint USDs with.
_minUSDSAmt
uint256
Minimum expected amount of USDs to be minted.
uint256
_deadline
uint256
Expiry time of the transaction.
_collateral
address
Address of the collateral.
_usdsAmt
uint256
Amount of USDs to be redeemed.
_minCollAmt
uint256
Minimum expected amount of collateral to be received.
_deadline
uint256
Expiry time of the transaction.
_collateral
address
Address of the collateral.
_usdsAmt
uint256
Amount of USDs to be redeemed.
_minCollAmt
uint256
Minimum expected amount of collateral to be received.
_deadline
uint256
Expiry time of the transaction.
_strategy
address
Address of the strategy to withdraw excess collateral from.
_collateral
address
Desired collateral address.
_usdsAmt
uint256
Amount of USDs to be redeemed.
calculatedCollateralAmt
uint256
Expected amount of collateral to be released based on the price calculation.
usdsBurnAmt
uint256
Expected amount of USDs to be burnt in the process.
feeAmt
uint256
Amount of USDs collected as fee for redemption.
vaultAmt
uint256
Amount of collateral released from Vault.
strategyAmt
uint256
Amount of collateral to withdraw from the strategy.
_collateral
address
Desired collateral address.
_usdsAmt
uint256
Amount of USDs to be redeemed.
_strategyAddr
address
Address of strategy to redeem from.
calculatedCollateralAmt
uint256
Expected amount of collateral to be released based on the price calculation.
usdsBurnAmt
uint256
Expected amount of USDs to be burnt in the process.
feeAmt
uint256
Amount of USDs collected as fee for redemption.
vaultAmt
uint256
Amount of collateral released from Vault.
strategyAmt
uint256
Amount of collateral to withdraw from the strategy.
_collateral
address
Address of collateral.
_collateralAmt
uint256
Amount of collateral.
uint256
Returns the expected USDs mint amount and fee for minting.
uint256
_collateral
address
Address of the collateral.
_collateralAmt
uint256
Amount of collateral to deposit.
_minUSDSAmt
uint256
Minimum expected amount of USDs to be minted.
_deadline
uint256
Deadline timestamp for executing mint.
_collateral
address
Address of the collateral to receive.
_usdsAmt
uint256
Amount of USDs to redeem.
_minCollateralAmt
uint256
Minimum expected collateral amount to be received.
_deadline
uint256
Deadline timestamp for executing the redemption.
_strategyAddr
address
Address of the strategy to withdraw from.
_collateral
address
Desired collateral address.
_usdsAmt
uint256
Amount of USDs to be redeemed.
_strategyAddr
address
Address of the strategy to redeem from.
calculatedCollateralAmt
uint256
Expected amount of collateral to be released based on the price calculation.
usdsBurnAmt
uint256
Expected amount of USDs to be burnt in the process.
feeAmt
uint256
Amount of USDs collected as a fee for redemption.
vaultAmt
uint256
Amount of collateral released from Vault.
strategyAmt
uint256
Amount of collateral to withdraw from the strategy.
strategy
IStrategy
Strategy contract to withdraw collateral from.
Inherits: ICollateralManager, Ownable
Author: Sperax Foundation
This contract manages the addition and removal of collateral, configuration of collateral strategies, and allocation percentages.
Collateral Manager interacts with the Vault and various strategies for collateral management.
Constructor to initialize the Collateral Manager
Parameters
_vault
address
Address of the Vault contract
Register a collateral for mint & redeem in USDs
Parameters
_collateral
address
Address of the collateral
_data
CollateralBaseData
Collateral configuration data
Update existing collateral configuration
Parameters
_collateral
address
Address of the collateral
_updateData
CollateralBaseData
Updated configuration for the collateral
Un-list a collateral
Parameters
_collateral
address
Address of the collateral
Add a new strategy to collateral
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the strategy
_allocationCap
uint16
Allocation capacity
Update existing strategy for collateral
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the strategy
_allocationCap
uint16
Allocation capacity
Remove an existing strategy from collateral
Ensure all the collateral is removed from the strategy before calling this Otherwise it will create error in collateral accounting
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the strategy
Validate allocation for a collateral
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the desired strategy
_amount
uint256
Amount to be allocated.
Returns
bool
True for valid allocation request.
Get the required data for mint
Parameters
_collateral
address
Address of the collateral
Returns
uint16
Base fee config for collateral (baseMintFee, baseRedeemFee, composition, totalCollateral)
uint16
uint16
uint256
Get the required data for mint
Parameters
_collateral
address
Address of the collateral
Returns
mintData
CollateralMintData
mintData
Get the required data for USDs redemption
Parameters
_collateral
address
Address of the collateral
Returns
redeemData
CollateralRedeemData
redeemData
Gets a list of all listed collaterals
Returns
address[]
List of addresses representing all listed collaterals
Gets a list of all strategies linked to a collateral
Parameters
_collateral
address
Address of the collateral
Returns
address[]
List of addresses representing available strategies for the collateral
Verifies if a strategy is linked to a collateral
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the strategy
Returns
bool
True if the strategy is linked to the collateral, otherwise False
Get the amount of collateral in all Strategies
Parameters
_collateral
address
Address of the collateral
Returns
amountInStrategies
uint256
amountInStrategies
Get the amount of collateral in vault
Parameters
_collateral
address
Address of the collateral
Returns
amountInVault
uint256
amountInVault
Get the amount of collateral allocated in a strategy
Parameters
_collateral
address
Address of the collateral
_strategy
address
Address of the strategy
Returns
allocatedAmt
uint256
Allocated amount
Inherits: IFeeCalculator
Author: Sperax Foundation
A contract that calculates fees for minting and redeeming USDs.
Calibrates fee for a particular collateral
Parameters
_collateral
address
Address of the desired collateral
Calculates fee to be collected for minting
Parameters
_collateral
address
Returns
uint256
(uint256) baseFeeIn
Calculates fee to be collected for redeeming
Parameters
_collateral
address
Returns
uint256
(uint256) baseFeeOut
Calibrates fee for all the collaterals registered
Helper function for calibrating fee for a collateral
Parameters
_collateral
address
Address of the desired collateral
Inherits: IDripper, Ownable
Author: Sperax Foundation
This contract releases tokens at a steady rate to the Vault contract, for rebasing the USDs stablecoin.
The Dripper contract ensures that tokens are released gradually over time, allowing for consistent and controlled distribution.
Constructor to initialize the Dripper.
Parameters
_vault
address
Address of the contract that receives the dripped tokens.
_dripDuration
uint256
The duration over which tokens are dripped.
Emergency fund recovery function.
Transfers the asset to the owner of the contract.
Parameters
_asset
address
Address of the asset to recover.
Function to be used to send USDs to dripper and update dripRate
.
Parameters
_amount
uint256
Amount of USDs to be sent form caller to this contract.
Transfers the dripped tokens to the vault.
This function also updates the dripRate based on the fund state.
Returns
uint256
The amount of tokens collected and transferred to the vault.
Update the vault address.
Parameters
_vault
address
Address of the new vault contract.
Updates the dripDuration.
Parameters
_dripDuration
uint256
The desired drip duration to be set.
Gets the collectible amount of tokens at the current time.
Returns
uint256
The amount of tokens that can be collected.
Inherits: IRebaseManager, Ownable
Author: Sperax Foundation
This contract handles the configuration and execution of the rebasing mechanism for the USDs stablecoin. It ensures that rebases occur only when certain prerequisites are fulfilled, such as the time gap between rebases and acceptable APR (Annual Percentage Rate) ranges.
The Rebase Manager coordinates with the Vault and Dripper contracts to manage the rebase process.
Constructor to initialize the Rebase Manager
Parameters
_vault
address
Address of the vault contract
_dripper
address
Address of the dripper contract for collecting USDs
_gap
uint256
Minimum time gap required between two consecutive rebases
_aprCap
uint256
Maximum allowed APR for a rebase
_aprBottom
uint256
Minimum allowed APR for a rebase
Get the current amount valid for rebase
Function is called by the vault while rebasing
Returns
uint256
The available amount for rebasing USDs
Updates the vault address
Parameters
_newVault
address
Address of the new vault contract
Updates the dripper contract for USDs vault
Parameters
_dripper
address
Address of the new dripper contract
Update the minimum time gap required between two rebases
Parameters
_gap
uint256
Updated gap time
Update the APR requirements for each rebase
Parameters
_aprBottom
uint256
New minimum APR for a rebase
_aprCap
uint256
New maximum APR for a rebase
Gets the current available rebase fund
Returns
uint256
Current balance in the vault plus collectable dripped USDs amount
Gets the minimum and maximum rebase USDs amount based on the APR config
Returns
uint256
Minimum and maximum rebase amounts
uint256
Stake SPA to earn rewards from fees and yield
SPA holders can stake SPA tokens on either Arbitrum or Ethereum and receive veSPA tokens which are non transferable. veSPA balance is proportional to the lockup period, meaning if user locks up for higher duration they receive proportionally more veSPA tokens. veSPA balance determines the share of staking reward and voting power
Staking rewards: rewards will be distributed proportionally to the user's veSPA balance. Users who lock SPA for longer periods are eligible for proportionally more rewards (accrued on a weekly base) than users who locked the same amount of SPA for shorter periods. Rewards are accumulated through:
Yield Share Rewards - 25% of the yield generated by USDs protocol.
Fee Rewards - 100% of the Fee income from USDs mints and redemptions.
The yield and fee income is originally generated in USDs. It is then swapped for SPA tokens before distribution. This makes the reward claiming process simple for stakers and maintains a constant buying pressure on the SPA token.
Voting power: once governance protocol is launched, voting power will depend on users' veSPA balance. Users who are committed to longer lockups will own more votes, whatever they are voting for.
veSPA balance at the moment of staking will not stay the same all the time - it will decay/reduce linearly. User's rewards per week and voting power will also decrease over time, together with the veSPA balance. Stakers can increase their veSPA balance and thereby their staking rewards and voting power by either extending the locking period or locking more SPA or re-staking SPA rewards.
At the end of the lockup period, veSPA balance will reduce depending on the pre-selected withdrawal option:
For Auto-cooldown option - to zero.
For the "Staying Staked" option (manual cooldown) - to [0.01917*staked SPA tokens]. Please note that for new stakers the "Staying Staked option" is not available.
To Stake SPA through our dapp checkout Stake SPA
veSPA is SPA locked with the "vote escrow" mechanism (ve-). This is the mechanism of locking tokens for relatively long pre-defined time periods. On staking SPA, the staker receives non-tranferrable tokens veSPA.
The veSPA balance will depend on the amount of SPA tokens locked and the user's chosen lockup period. Stakers can lock their tokens for a maximum of 4 years or a minimum of 7 days. A higher lockup period means a higher veSPA balance for the same amount of SPA staked.
veSPA value = SPA tokens staked * (Lockup Period in days / 365)
Below table shows how veSPA value will be determined
4 year
1
4
3 year
1
3
2 year
1
2
1 year
1
1
6 months
1
0.5
veSPA balance will decay linearly with time. At the end of lockup period, veSPA balance will reduce to 0 or (0.01917*staked SPA tokens) based on the withdrawal method user chooses while staking the SPA. Two withdrawal methods were available to the early stakers, they will work till the end of their lockup period. For all the new stakers method 1 (Auto-cooldown) stays the only available method.
Auto-cooldown - veSPA balance reduces to 0 at the end of lockup period and staker is able to withdraw locked SPA balance immediately after expiry date
Stay Staked at Residual Value - Stakers can opt to remain staked at the end of the unlock date at a residual veSPA balance (0.01917*staked SPA tokens). They can initiate cooldown when 7 days are left in the staking period or anytime after. After the cooldown period of 7 days is over, they can withdraw the staked SPA tokens. Check outStay Staked at Residual Valuefor more details.
Some important points to consider before locking your SPA tokens:
Staking is an irreversible process, once locked the tokens cannot be unlocked before the unlock date. Users cannot prepone the expiry date or reduce the amount of locked SPA.
Due to precision issues it may not always be possible to choose an exact unlock date. Users can select the lockup period but the exact unlock date is rounded down to nearest Thursday UTC. Stakers will be able to choose these eligible unlock dates in our dapp.
Users rewards per week and voting power will also decrease over time, together with the veSPA balance. The users who are committed to long-term staking can increase their rewards per week and voting power by:
Extending the locking period
Locking more SPA
Claiming SPA staking rewards and restaking them into veSPA (compounding)
Stakers can extend their lockup such that the lockup expiry date is <= 4 years from the current date. At no point, lockup period can be more than 4 years.
The lockup period cannot be extended in the following scenarios:
When a staker’s lockup period has expired and they only have residual veSPA balance
When a staker has already initiated cooldown period Example: If a user has 100 veSPA tokens which expire in 3 years, the user can increase the lockup by a maximum of 1 year.
Users can also increase their veSPA balance by staking any additional amount of SPA tokens for the same lockup as their existing veSPA balance.
Example: if a user has 100 veSPA tokens which are expiring in 34 days, they can stake any amount of additional SPA for 34 days. The increase in veSPA balance will be calculated based on the same lockup period as the previously staked tokens.
Users who initiate staking will get the auto-cooldown feature. Users who initiated staking in the past were able select one of two cooldown options that will stay active till the end of the staking period:
Auto-cooldown: the protocol will automatically initiate a cooldown 7 days before expiry. In this case, the assets will be available immediately after the lock period, but they will not bring any more rewards post-expiry.
Stay staked at residual value (or manual cooldown): After the lock expires, the assets remain locked with the residual value of [0.01917*staked SPA tokens], and will continue to bring rewards to the user. If one day the user decides to take their assets out - they need to initiate the cooldown manually. After a one-week cooldown, the assets will become available.
Withdrawing from the protocol does not automatically claim all the SPA rewards. The users would be required to claim the rewards separately. In case the staking rewards are not distributed till that point of time, users can still claim the rewards and fee earnings accrued to them after they have withdrawn their staked SPA tokens.
When new users start staking, the auto-cooldown feature is applied. Auto-cooldown means that the veSPA balance decays to zero linearly and the stakers are able to withdraw their staked SPA balance at the end of their lockup period.
Currently, this option is not available. If a user has chosen this option while staking in the past, their final veSPA balance was set at the residual veSPA balance. They would continue to earn all the staking rewards at this veSPA balance for as long as the protocol keeps distributing rewards. The residual veSPA balance is equivalent to the veSPA balance of a staking position that unlocks in 7 days.
Residual veSPA balance = (7/365)*Staked SPA tokens = 0.01917*Staked SPA tokens
Stakers can initiate cooldown when 7 days are left in lockup expiry or anytime after that. When the staker’s veSPA balance is set to the residual veSPA balance or when only 7 days are left in the lockup period, the staker can initiate a transaction to start a cooldown period. When the cooldown period is initiated the lockup expiry date is updated to a new date which would be 7 days from the date on which the cooldown was initiated.
Staker’s veSPA balance decays from the residual veSPA balance to zero during the cooldown period. At the end of the cooldown period, the staker can withdraw the SPA they had deposited. Stakers receive rewards during the cooldown period in proportion to their veSPA balance.
At the end of the cooldown period, the veSPA balance remains zero and the user doesn’t get any rewards. The users can unstake at any point in time after the cooldown period has ended.
ERC20 contract
USDs is a stable coin which generates auto-yield natively.
USDs is a rebasing token with two modes of accounting for users:
Rebasing wallets
Users holding tokens in their EOA are by default in this category and are eligible for auto-yield via a rebasing mechanism.
Any contract opted-in for rebase also comes in this category.
Balance for this category is tracked via a credit system, as described below :
creditsPerToken is tracked at a global level and is updated when doing a rebase.
creditBalance is tracked at an account level and is updated via token transfer, mint, redemption of USDs
Non-Rebasing wallets
For Non-Rebasing wallets this token acts as a normal ERC20 token and tracks the balance of the wallet as usual.
Rebasing Mechanism
Users mint USDs using approved list of collaterals
These collaterals accumulated in the USDs vault are then deployed to various yield on-chain earning opportunities.
Yield is harvested periodically and is used to buyback USDs from the market of which 50% is used as revenue for veSPA holders and rest of it goes for USDs auto yield.
While doing a rebase the x amount of USDs is partially burnt (without changing the overall total supply) and the creditsPerToken
value is adjusted such that the burnt amount is proportionally distributed across all rebasing wallets.
Author: Sperax Foundation
ERC20 compatible contract for USDs supporting the rebase feature. This ERC20 token represents USDs on the Arbitrum (L2) network. Note that the invariant holds that the sum of balanceOf(x) for all x is not greater than totalSupply(). This is a consequence of the rebasing design. Integrations with USDs should be aware of this feature.
Verifies that the caller is the Savings Manager contract.
Initializes the contract with the provided name, symbol, and vault address.
Parameters
Mints new USDs tokens, increasing totalSupply.
Parameters
Burns tokens, decreasing totalSupply.
Parameters
Voluntary opt-in for rebase.
Useful for smart-contract wallets.
Voluntary opt-out from rebase.
Adds _account
to the rebasing account list.
Parameters
Adds _account
to the non-rebasing account list.
Parameters
The rebase function. Modifies the supply without minting new tokens. This uses a change in the exchange rate between "credits" and USDs tokens to change balances.
Parameters
Change the vault address.
Parameters
Called by the owner to pause or unpause the contract.
Parameters
Transfer tokens to a specified address.
Parameters
Returns
Transfer tokens from one address to another.
Parameters
Returns
Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. This method is included for ERC20 compatibility.
increaseAllowance and decreaseAllowance should be used instead. Changing an allowance with this method brings the risk that someone may transfer both the old and the new allowance - if they are both greater than zero - if a transfer transaction is mined before the later approve() call is mined.
Parameters
Returns
Increase the amount of tokens that an owner has allowed a _spender
to spend. This method should be used instead of approve() to avoid the double approval vulnerability described above.
Parameters
Returns
Decrease the amount of tokens that an owner has allowed a _spender
to spend.
Parameters
Returns
Check the current total supply of USDs.
Returns
Gets the USDs balance of the specified address.
Parameters
Returns
Gets the credits balance of the specified address.
Parameters
Returns
Function to check the amount of tokens that an owner has allowed a spender.
Parameters
Returns
Creates _amount
tokens and assigns them to _account
, increasing the total supply.
Emits a {Transfer} event with from
set to the zero address.
Requirements - to
cannot be the zero address.
Parameters
Destroys _amount
tokens from _account
, reducing the total supply.
Emits a {Transfer} event with to
set to the zero address.
Requirements:
_account
cannot be the zero address.
_account
must have at least _amount
tokens.*
Parameters
For non-rebasing accounts credit amount = _amount
Update the count of non-rebasing credits in response to a transfer
Parameters
Add a contract address to the non-rebasing exception list. I.e., the address's balance will be part of rebases so the account will be exposed to upside and downside.
Parameters
Remove a contract address from the non-rebasing exception list.
Is an account using rebasing accounting or non-rebasing accounting? Also, ensure contracts are non-rebasing if they have not opted in.
Parameters
Ensures internal account for rebasing and non-rebasing credits and supply is updated following the deployment of frozen yield change.
Parameters
Calculates the balance of the account.
Function assumes the _account is already upgraded.
Parameters
Get the credits per token for an account. Returns a fixed amount if the account is non-rebasing.
Parameters
Validates if the contract is not paused.
Inherits: Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable
Author: Sperax Foundation
Contract acts as a single interface for implementing specific yield-earning strategies.
Update the linked vault contract.
Parameters
Updates the HarvestIncentive rate for the user.
Parameters
A function to recover any erc20 token sent to this strategy mistakenly.
Only callable by owner.
reverts if amount > balance.
Parameters
Deposit an amount of asset into the platform.
Parameters
Withdraw an amount of asset from the platform.
Parameters
Returns
Withdraw an amount of asset from the platform to vault.
Parameters
Withdraw the interest earned of asset from the platform.
Parameters
Collect accumulated reward token and send to Vault.
Get the amount of a specific asset held in the strategy, excluding the interest.
Curve: assuming balanced withdrawal.
Parameters
Returns
Get the amount of a specific asset held in the strategy, excluding the interest and any locked liquidity that is not available for instant withdrawal.
Curve: assuming balanced withdrawal.
Parameters
Returns
AAVE: Get the interest earned on a specific asset. Curve: Get the total interest earned.
Curve: to avoid double-counting, _asset has to be of index 'entryTokenIndex'.
Parameters
Returns
Get the amount of claimable reward.
Returns
Get the total LP token balance for a asset.
Parameters
Check if an asset/collateral is supported.
Parameters
Returns
Change to a new depositSlippage & withdrawSlippage.
Parameters
Initialize the base properties of the strategy.
Parameters
Provide support for asset by passing its pToken address. Add to internal mappings and execute the platform specific, abstract method _abstractSetPToken
.
Parameters
Remove a supported asset by passing its index. This method can only be called by the system owner.
Parameters
Returns
Splits and sends the accumulated rewards to harvestor and yield receiver.
Sends the amount to harvestor as per harvestIncentiveRate
and sends the rest to yield receiver.
Parameters
Returns
Call the necessary approvals for the underlying strategy.
Parameters
This technical document is about the upgrade to Demeter-v2. It details the changes made to enhance the protocol's multi chain vision, transparency, security, and scalability. The document covers new features and functionalities.
Works on Arbitrum Uniswap V2, Uniswap V3, Camelot V2, Camelot V3 and Balancer V2.
Demeter protocol is a protocol for DAOs to launch and manage decentralized exchange liquidity - without needing to know how to code. Demeter gives users the power to launch incentivized liquidity pools on Uniswap V3 and Camelot V2. Future versions will support custom liquidity shapes on major DEXs such as Balancer, Sushiswap or anything veSPA holders prefer. Demeter is launched on Arbitrum and will be expanded to Optimism, Polygon and Ethereum soon. Additional blockchains will be added in future versions.
Demeter automates the fundamental aspects of launching and managing decentralized exchange liquidity for the DAOs native token:
Engineering support to launch and manage the farm - The Audited Demeter Farm Factory contract will generate the pool and farm contracts for the Demeter user.
Marketing support to make the community aware of the new farm - Protocols that launch their farm through Demeter benefit from being whitelisted on the Demeter active farms dashboard. This exclusive list features all of the farms that are actively distributing rewards that were deployed with Demeter. Farmers will regularly look to this dashboard for new projects and become users of these protocols.
On Arbitrum, Uniswap has less liquidity than Balancer and Sushiswap. This is because Sushiswap uses the simple Uniswap V2, x*y=k approach. This is simple because all LP tokens are the same, but penalizes the LP because they are forced to provide liquidity from 0 to infinity. Incentivized liquidity pools on Uniswap V3 lets DAOs benefit from concentrated liquidity - the same TVL offers less slippage compared to diluted liquidity. This directly translates to a lower emissions budget for other protocols and much more fees for LPs.
To launch a Uniswap V3 or Camelot V3 farm, DAOs are currently expected to write complicated V3 farm contracts, get the contracts audited, incentivize LP deposits with only their native token, then promote this new pool. With Demeter, DAOs can launch these farms without knowing how to code and get marketing and technical support from Sperax. DAOs can also launch their farms on Camelot V2, their farms can get rewards both in SPA and Camelot tokens (xGRAIL/GRAIL) that decrease DAO's token spend and decrease sale pressure on it.
In Demeter Protocol V2, we have focused more on the protocol's multichain vision and to support that, we have discontinued incentives on pairing with SPA and USDs as these tokens are not available on all the chains. Now the fee params are configurable in in the farm registry contract, more details in the next section.
veSPA holders or stakers get SPA token rewards in proportion to their veSPA balance. Users have an option to stake their SPA rewards directly into the staking protocol instead of claiming, thereby compounding their veSPA balances.
veSPA holders or stakers will receive 3 kinds of rewards. All the three kinds of rewards are distributed with the same mechanism and in the form of SPA tokens.
100% of the USDs Fees generated by USDs protocol
25% of yield generated by USDs deployed collateral
Incentives sponsored by Treasury to bootstrap the Staking protocol - This emission has been set to 0 through governance
The USDs protocol fees collected will be distributed across all veSPA holders on a pro rata basis. With the fees collected by the USDs protocol the Staking protocol will purchase SPA tokens from the market and distribute the SPA tokens amongst all veSPA holders.
50% of the yield generated by the USDs protocol will be swapped for SPA tokens. 50% of the SPA bought back will be burnt and remaining 50% will be distributed to veSPA holder. So the fraction of yield that is shared with the veSPA holders is 25% (50% x 50%). These parameters can be changed by the community through governance proposal.
A separate SPA reward budget was set aside from Treasury to bootstrap staking protocol. Incentive rewards for staking was initially set at a fixed daily distribution number of 54.794 K SPA. This number was later changed through governance and set to 0 to reduce SPA inflation.
Staking reward distribution happens on a weekly basis. New weeks start on Thursdays at 00:00:00 UTC. Rewards are distributed at the end of each week.
‘Stake-Reward-Claim-Repeat’ is a four-step cycle:
Stake SPA - In Week 1, you stake SPA and obtain veSPA. Reward accumulation starts from Week 2.
Reward distribution for Week 2 occurs at the end of the Week 2
Total staking reward available for distribution in Week 2 is based on USDs fee income that was collected, the yield that was generated by the USDs protocol and the daily distribution rate of the SPA staking incentives for Week 2
User’s share of staking rewards for Week 2 is calculated based on their veSPA balance at the starting of Week 2 relative to the total veSPA supply at the starting of week 2
Rewards for Week 2 can be claimed by users from Week 3 onwards. Users can also stake their SPA rewards and increase their veSPA balance and future rewards.
Step 2 and 3 repeat every week till expiry
Reward distribution for Week X occurs at the end of the Week X
Rewards for Week X can be claimed by users from Week X+1 onwards.
Total SPA Rewards for the week = Staking Incentive Rewards + USDs Fees Rewards + USDs Yield Share Rewards
where Staking Incentive Rewards = Daily Incentive Rewards*7
USDs Fees Rewards = USDs Fee earned*USDs Price / SPA price
USDs Yield Share Rewards = 50%*USDs yield earned in the week * USDs price/ SPA price
The above formula is an assumption, actual SPA rewards from USDs fees and yield would differ based on the asset prices in the open market
Total SPA Rewards for the week = R
Total veSPA balance of the protocol at the start of the week = V
User’s veSPA balance at the start of the week = v
User’s SPA staked at the start of the week = s
User's staking duration in years = d = v/s
Weekly Reward Earned by a user = r = (R/V)*v
Staking APR
= (Weekly Reward Earned by a user /SPA staked by user)*(365/7)*100%
= (r/s)*(365/7)*100%
= (R/V)*(v/s)*(365/7)*100%
= (R/V)*d *(365/7)*100%
Staking APY
= [{1+ (Weekly Reward Earned by a user /SPA staked by user)}^(365/7) -1] * 100%
= [{1+ (r/s)}^(365/7) -1] * 100%
= [{1+ (R/V)*(v/s)}^(365/7) -1] * 100%
= [{1+ (R/V)*d}^(365/7) -1] * 100%
Calculation of APY assumes that the weekly rewards are re-staked in the protocol
Demeter is a protocol that enables DAOs to launch and manage decentralized exchange (DEX) liquidity pools and farms on platforms like Uniswap V2, Uniswap V3, Camelot V2, Camelot V3 and Balancer V2. The protocol simplifies the process of incentivizing liquidity for the DAOs' native tokens without requiring coding expertise. Demeter automates the creation, management, and reward distribution for liquidity pools, providing support in engineering, marketing, and financial incentives.
Approve Fees Spend: Users must first approve the spending of the fee token for the farm creation fee. The fee is 100 USDs on Arbitrum. On any chain not supporting USDs, it can be any other stable coin supported on that chain.
Input Pool and Farm Parameters: Users must provide necessary parameters for the pool and farm.
Execute Transaction: A transaction is executed to create the farm and pay the farm creation fee.
Reversion Conditions:
If the pool does not exist, the transaction reverts.
If the user does not have enough fee tokens to pay the fee, the transaction reverts.
Token address
Token A
Token B
Fee Tier (for Uniswap V3 Pools)
Liquidity Parameter L - An LP token parameter which is set based on the user’s liquidity inside the pool. Updating this parameter will allow the farm users to add or remove liquidity. When the LP token is updated, the LP token should start receiving rewards based on the new L parameter. This will allow users to add or remove liquidity without having to unstake their entire LP position.
Active Liquidity Time Check - (a Boolean value of true or false which determines whether the position is in the current price range) - To check if the position is in the current price range, as only that liquidity will be rewarded which is in range. However, users will be allowed to remove any locked liquidity during the period when the liquidity is not in the current price range.
Farm admin: It is the address that will have admin control on the farm. It can be the same as the deployer’s address or any other desired address which will be used to manage the farm.
Price range for the LP
Reward tokens
Token addresses
Token address managers: Each token will have its own token manager.
Reward tokens have to be added at the time of farm creation and can't be added or removed after the farm is created. Maximum 4 reward tokens are possible for a farm.
For reward tokens emitting fixed APR, Token manager will be the Rewarder contract deployed through the Rewarder factory.
Cooldown Period for Locked Liquidity - It is the number of days users have to wait after initiating cooldown before they can unstake from a locked position. Only whole numbers are allowed for this parameter.
If Cooldown Period = 0, then the farm only allows creation of unlocked positions. Unlocked positions can be unstaked anytime.
If Cooldown Period > =1, the farm will allow creation of both locked and unlocked positions. For unstaking a locked position, users have to initiate cooldown and wait for cooldown period before unstaking.
Start date time stamp - Reward emission starts from this date. This date can be changed by the farm admin using admin functions (updateFarmStartTime). However, date change is not allowed after the farm starts.
The farms start accepting liquidity immediately after the creation of the farm contract. However, the reward accrual starts from the farm start date time stamp.
Annual Percentage Return APR - The farm admin can set a fixed APR which will guarantee a reward to the LPs based on the current price of the reward tokens. The farm admin will also have to choose one or more base tokens out of the tokens present in the farm for calculation of the daily number of reward tokens emitted.
Let’s say APR set = APR%.
Total value of Base Tokens in USD = Σ (Number of Base tokens in farm x USD value of Base Token)
No. of Reward tokens per day = [(APR x Total value of Base Tokens in USD) / (100 x 365)] / (Price of 1 reward token based on the oracle)]
Maximum number of Rewards Tokens Emitted Per Day - The farm admin would be able to add the maximum number of reward tokens per day that the farm can distribute, to prevent any deficiency in the farm’s reward tokens in cases when many LPs deposit on the same day since then all the withdrawals may also happen on the same day.
It will override the reward tokens value calculated using the formula mentioned above in point no 6. The rewards emitted per day will be the minimum of the amount calculated above or the max reward rate set by the reward manager.
This is a new feature which has all the above parameters along with the expiry date feature:
Expiry Date - Farms will have an expiry date associated with them. Users can specify the expiry date while creating the farms. The initial launch fee of 100 USDs (or some other stable coin if USDs is not present on that chain) will add 100 days to the farm expiry. After that users have the option to extend the farm expiry date. Post that users will have to extend the farm in the multiple of 1 USDs/day with minimum of 100 days at a time and a maximum of 300 days.
Farm admins will not be able to update any farm parameters once the farm has expired. However, they can remove any unclaimed reward tokens from the contract.
Farm users can still claim any accrued rewards from the farm or remove liquidity from them once that farm has expired.
Farms that have expired will be available on the Dashboard for removing liquidity up to 30 days beyond expiry. After that the farms will only appear on the expired farm list and admins cannot make the expired farms active again. Users or admins will be able to apply all actions through the smart contract.
Expired farms shall be removed from the Sperax Gauge and would not be eligible for SPA rewards.
Farm does not accrue rewards after the expiration so users can call updateFarmRewardData function on the farm to accrue rewards before farmEndTime to avoid any loss of rewards.
Demeter will charge a flat $100 fee to launch the farm, which will add 100 days to the expiry date set while the creation of the farm.
After that users have the option to extend the farm expiry date. They can do so in the multiple of 1 USDs/day with minimum of 100 days at a time and a maximum of 300 days. The fees can be paid in either USDs or in any other stable coin provided USDs is not present in that chain.
The fee collected belongs to the SPA stakers and can be transferred directly to the wallet address where all Sperax protocol fees are collected. Fee amount can be changed in future through governance.
The Fee details can be fetched from getFeeParams function on the Farm registry contract.
No one can make changes to the farm contract once deployed. Farm admins can do the following:
Transfer farm ownership to another address
Change start date of the farm - Farm will emit rewards from this date. The date can be changed after farm creation. However, date change is not allowed after the farm starts.
Update cooldown period of the locked positions
Pause or Unpause the farm
Pause the farm - All reward distributions are paused, LPs do not earn any rewards during this period. Withdrawals are allowed (including lockup LPs) and users can also claim previously accrued rewards. Admin/managers can make changes to the distribution rates and the other parameters when the farm is paused.
Unpause the farm - Resume the reward distribution. The reward distribution rate remains the same as set by the reward managers.
Update Expiry Date of the Farm by paying Subscription Fees
Farm admins can choose and update the expiry date of farms as mentioned in the Farm Parameters.
Close the farm - The farms can be closed before the expiry date and will automatically get closed once the expiry date is reached. Once the farm is closed, all liquidity providers including lockup users can now unstake their liquidity pool tokens and claim the accrued rewards from the farm.
Each reward token will be assigned a reward token manager. Farm admin cannot update the reward token manager once the farms are deployed. Reward token managers can do the following:
Add reward token balance
Update reward distribution rate per second for each token. Only future distribution rates can be affected through this. Reward distribution can be paused by setting the rate to 0. These actions can be done:
For all liquidity providers.
For lockup liquidity providers (If cooldown period is greater than 0)
Changing the maximum number of token rewards per day - Farm admins can increase or decrease the reward tokens limit in the fixed APR model as per their choice.
Withdraw reward tokens (Any rewards already accrued to LPs cannot be removed).
Transfer reward token management to another address.
Select the farm: LPs need to choose the required farm from the whitelisted farms which are present on the dashboard, based on their choice of tokens and price range.
Enter the number of farm tokens: Post that, they can enter the number of one of the tokens for the position, the other tokens are automatically calculated.
Execute Transaction: The user then needs to approve the wallet transactions for the spending of tokens and creation of a farm position.
Reversion Conditions:
If the user does not have the required tokens in their wallet, the transaction reverts.
LP Token: On successful execution of the transaction, the Liquidity Provider will receive the LP token(s) in their wallet.
Depositing the LP Token: Users then need to deposit the lp tokens inside the farm to create a position.
Updating the Liquidity Balance - This will allow LPs to add to or remove liquidity from the LP Token without having to unstake their entire LP position. When the LP token is updated, the LP token should start receiving rewards based on the new L parameter.
Fixed APR Rewards - The LPs will receive fixed APR rewards (this fixed APR will be set by the farm admin) generated from their invested farms. Each farm will have some base reward tokens which will be the base for calculating the number of reward tokens to be emitted per day. The LP will receive the reward tokens (selected by the farm admin) in their wallet, which will be calculated as:
Let’s say APR set = APR%.
Total value of Base Tokens in USD = Σ (Number of Base tokens in farm x USD value of Base Token)
No. of Reward tokens per day = [(APR x Total value of Base Tokens in USD) / (100 x 365)] / (Price of 1 reward token based on the oracle)]
Maximum number of Rewards Tokens Emitted Per Day - However, the number of reward tokens to be emitted by the farm has been capped. The farm admin would be able to add the maximum number of reward tokens per day that the farm can distribute, to prevent any deficiency in the farm’s reward tokens in cases when many LPs deposit on the same day since then all the withdrawals may also happen on the same day.
Inherits: ReentrancyGuard, Ownable
Author: Sperax Foundation
This contract allows users to swap supported stable-coins for yield earned by the USDs protocol. It sends USDs to the Dripper contract for rebase and to the Buyback Contract for buyback.
Constructor of the YieldReserve contract.
Parameters
Swap function to be called by frontend users.
Parameters
Allow or disallow a specific token
for use as a source/input token.
Parameters
Allow or disallow a specific token
for use as a destination/output token.
Reverts if caller is not owner.
Parameters
Emergency withdrawal function for unexpected situations.
Parameters
Set the percentage of newly minted USDs to be sent to the Buyback contract.
Reverts if caller is not owner.
The remaining USDs are sent to VaultCore for rebase.
Parameters
Update the address of the Buyback contract.
Reverts if caller is not owner.
Parameters
Update the address of the Oracle contract.
Reverts if caller is not owner.
Parameters
Update the address of the Dripper contract.
Reverts if caller is not owner.
Parameters
Update the address of the VaultCore contract.
Reverts if caller is not owner.
Parameters
Swap allowed source token for allowed destination token.
Parameters
Mints USDs directly with the allowed collaterals for USDs.
Only collaterals configured in USDs vault are allowed to be used for minting.
Parameters
Get an estimate of the output token amount for a given input token amount.
Parameters
Returns
Distributes USDs to the Buyback and Dripper contracts based on buybackPercentage.
Sends a portion of the USDs balance to the Buyback contract and the remaining to the Dripper contract for rebase.
Inherits: Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable
Author: Sperax Foundation
This contract allows users to exchange SPA tokens for USDs tokens.
Users can provide SPA tokens and receive USDs tokens in return based on the current exchange rate.
A percentage of the provided SPA tokens are distributed as rewards, and the rest are burned.
Contract initializer
Parameters
Emergency withdrawal function for unexpected situations
Can only be called by the owner
Parameters
Changes the reward percentage
Example value for _newRewardPercentage = 5000 for 50%
Parameters
Update veSpaRewarder address
Parameters
Update oracle address
Parameters
Function to buy USDs for SPA for frontend
Parameters
Calculates and returns SPA amount required for _usdsAmount
Parameters
Returns
Buy USDs for SPA if you want a different receiver
Parameters
Sends available SPA in this contract to rewarder based on rewardPercentage and burns the rest
Returns the amount of USDS for SPA amount in
Parameters
Returns
Returns the amount of USDS for SPA amount in
Parameters
Returns
Retrieves price data from the oracle contract for SPA and USDS tokens.
Returns
Checks if the provided reward percentage is valid.
The reward percentage must be a non-zero value and should not exceed the maximum percentage value.
Parameters
Buyback contract is designed to decentralize the SPA buyback process while adding a boosting mechanism to continuously grow USDs TVL with protocol revenue (Yield + Fee). This contract allows users to directly purchase USDs with SPA. The available-for-purchase USDs comes from two sources - USDs mint/redeem fees and USDs yield. The contract distributes 50% of the SPA bought back from users to veSPA holders as reward and burns the rest.
Protocol Yield - The yield is collected in multiple tokens through pool fee (USDC, FRAX, etc) and farm rewards (like FXS, STG etc.). This yield is converted to USDs. A portion is sent to buyback contract and remaining to auto-yield reserve.
Swap yield tokens to eligible collateral tokens (for minting USDs) using DEXes based on the path of lowest slippage
Mint USDs using the collateral tokens
Deposit 50% of the yield (USDs received in previous step) that will be used to buyback SPA into the buyback contract and the rest of the USDs is transferred back to the USDs vault’s auto-yield reserve. Yield share percentage is set to 50% currently and can be changed in future through governance.
Protocol Fee - Mint and redemption fee from the USDs protocol is collected in the form of USDs. This component is directly deposited to the Buyback contract.
Buyback SPA - Any users or external wallet can view the USDs balance in the Buyback contract and sell their SPA tokens for USDs.
Burn 2.0 - 50% of the SPA received in step 4 is burnt and remaining 50% is sent to veSPA rewarder. The burn percentage can be changed through governance.
Sperax protocol deposits USDC.e to Stargate strategy (Stargate-LP USDC.e) and stakes LP tokens. Protocol earns STG token.
Sell STG tokens for USDC.e
Mint USDs from USDC.e
Transfer USDs to the Buyback contract.
Deposit USDs Mint and Redemption Fees directly into the Buyback contract as and when they are collected
Users can view the amount of USDs left in the contract
USDs is bought by the users using their SPA and contract receives SPA against the USDs
getSPAReqdForUSDs - Input the target USDs amount to receive and get an estimate of how many SPA tokens are needed.
Function: getSPAReqdForUSDs(uint256 _usdsAmount) external view returns (uint256)
Input : _usdsAmount is the amount of USDs to purchase
Output: Estimated amount of SPA required
Example: Suppose getSPAReqdForUSDs(1e18) returns 100*1e18. It means the contract estimates that one will need to speed 100 SPA to purchase 1 USDs at this moment.
getUsdsOutForSpa - Input the amount of SPA to be sold and get an estimate of how many USDs can be purchased.
Function: getUsdsOutForSpa(uint256 _spaIn) external view returns (uint256)
Input : _spaIn is the amount of SPA to be sold
Output: Estimated amount of USDs to be received
Example: Suppose getSPAReqdForUSDs(100*1e18) returns 1e18. It means the contract estimates that one will receive 1 USDs after spending 100 SPA.
buyUSDs - Purchase USDs with SPA
Function: buyUSDs(uint256 _spaIn, uint256 _minUSDsOut) external
Input : _spaIn is the amount of SPA to be sold _minUSDsOut is the minimum amount of USDs to be received
Output : The contract will extract _spaIn amount of SPA from the wallet executing the transaction, exchange it to USDs, and send USDs back to the wallet
Example : Suppose wallet A triggers buyUSDs(100*1e18, 1e18) (after he has already approved the Buyback contract to spend its SPA). The contract will extract 100 SPA from A, exchange it to USDs, and send USDs back to A.
buyUSDs - Purchase USDs with SPA (arbitrary USDs receipt)
Function: buyUSDs(address _receiver, uint256 _spaIn, uint256 _minUSDsOut) external
Input : _receiver is the receiver of the purchased USDs _spaIn is the amount of SPA to be sold _minUSDsOut is the minimum amount of USDs to be received
Output : The contract will extract _spaIn amount of SPA from the wallet executing the transaction, exchange it to USDs, and send USDs to the _receiver wallet
Example : Suppose wallet A triggers buyUSDs(B, 100*1e18, 1e18) (after he has already approved the Buyback contract to spend its SPA). The contract will extract 100 SPA from A, exchange it to USDs, and send USDs to B.
USDs
Vault
CollateralManager
FeeCalculator
MasterPrice Oracle
SPABuyback
YieldReserve
Dripper
RebaseManager
AaveStrategy
StargateStrategy
CompoundStrategy
Inherits: ERC20PermitUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable,
Inspired by OUSD:
The yield and fee income is swapped for SPA tokens before distribution. The SPA that is bought back from the open markets using 50% of the auto-yield and 100% of the fees is stored in : (Arbitrum One)
_nameArg
string
The name of the USDs token.
_symbolArg
string
The symbol of the USDs token.
_vaultAddress
address
The address where collaterals of USDs protocol reside, and major actions like USDs minting are initiated.
_account
address
The account address to which the newly minted USDs will be attributed.
_amount
uint256
The amount of USDs to be minted.
_amount
uint256
The amount to burn.
_account
address
Address of the desired account.
_account
address
Address of the desired account.
_rebaseAmt
uint256
The amount of USDs to rebase with.
_newVault
address
The new vault address.
_pause
bool
The state of the pause switch.
_to
address
The address to transfer to.
_value
uint256
The amount to be transferred.
bool
True on success.
_from
address
The address from which you want to send tokens.
_to
address
The address to which the tokens will be transferred.
_value
uint256
The amount of tokens to be transferred.
bool
true on success.
_spender
address
The address that will spend the funds.
_value
uint256
The amount of tokens to be spent.
bool
true on success.
_spender
address
The address that will spend the funds.
_addedValue
uint256
The amount of tokens to increase the allowance by.
bool
true on success.
_spender
address
The address that will spend the funds.
_subtractedValue
uint256
The amount of tokens to decrease the allowance by.
bool
true on success.
uint256
The total supply of USDs.
_account
address
The address to query the balance of.
uint256
A uint256 representing the amount of base units owned by the specified address.
_account
address
The address to query the balance of.
uint256
(uint256, uint256) Credit balance and credits per token of the address.
uint256
_owner
address
The address that owns the funds.
_spender
address
The address that will spend the funds.
uint256
The number of tokens still available for the spender.
_account
address
The account address to which the newly minted USDs will be attributed.
_amount
uint256
The amount of USDs that will be minted.
_account
address
The account address from which the USDs will be burnt.
_amount
uint256
The amount of USDs that will be burnt.
_from
address
The address from which you want to send tokens.
_to
address
The address to which the tokens will be transferred.
_value
uint256
Amount of USDs to transfer
_account
address
address of the account opting in for rebase.
_account
address
Address of the account.
_account
address
Address of the account.
_account
address
Address of the account.
_account
address
Address of the account.
_newVault
address
Address of the new Vault.
_newRate
uint16
new Desired rate.
token
address
Address of the token.
receiver
address
Receiver of the token.
amount
uint256
Amount to be recovered.
_asset
address
Address for the asset.
_amount
uint256
Units of asset to deposit.
_recipient
address
Address to which the asset should be sent.
_asset
address
Address of the asset.
_amount
uint256
Units of asset to withdraw.
amountReceived
uint256
The actual amount received.
_asset
address
Address of the asset.
_amount
uint256
Units of asset to withdraw.
_asset
address
Address of the asset.
_asset
address
Address of the asset.
uint256
uint256 Balance of _asset in the strategy.
_asset
address
Address of the asset.
uint256
uint256 Available balance inside the strategy for _asset.
_asset
address
Address of the asset.
uint256
uint256 Amount of interest earned.
RewardData[]
struct array of type RewardData (address token, uint256 amount).
_asset
address
Address of the asset.
_asset
address
Address of the asset.
bool
bool Whether asset is supported.
_depositSlippage
uint16
Slippage tolerance for allocation.
_withdrawSlippage
uint16
Slippage tolerance for withdrawal.
_vault
address
Address of the USDs Vault.
_depositSlippage
uint16
Allowed max slippage for Deposit.
_withdrawSlippage
uint16
Allowed max slippage for withdraw.
_asset
address
Address for the asset.
_pToken
address
Address for the corresponding platform token.
_assetIndex
uint256
Index of the asset to be removed.
asset
address
address which is removed.
_token
address
Address of the reward token.
_yieldReceiver
address
Address of the yield receiver.
_harvestor
address
Address of the harvestor.
_amount
uint256
to be split and sent.
uint256
uint256 Harvested amount sent to yield receiver.
_asset
address
Address of the asset.
_pToken
address
Address of the corresponding receipt token.
_buyback
address
Address of the Buyback contract.
_vault
address
Address of the Vault.
_oracle
address
Address of the Oracle.
_dripper
address
Address of the Dripper contract.
_srcToken
address
Source/Input token.
_dstToken
address
Destination/Output token.
_amountIn
uint256
Input token amount.
_minAmountOut
uint256
Minimum output tokens expected.
_token
address
Address of the token to be allowed or disallowed.
_isAllowed
bool
If set to true, the token will be allowed as a source/input token; otherwise, it will be disallowed.
_token
address
Address of the token to be allowed or disallowed.
_isAllowed
bool
If set to true, the token will be allowed as a destination/output token; otherwise, it will be disallowed.
_token
address
Address of the asset to be withdrawn.
_receiver
address
Address of the receiver of tokens.
_amount
uint256
Amount of tokens to be withdrawn.
_toBuyback
uint256
The percentage of USDs sent to Buyback (e.g., 3000 for 30%).
_newBuyBack
address
New address of the Buyback contract.
_newOracle
address
New address of the Oracle contract.
_newDripper
address
New address of the Dripper contract.
_newVault
address
New address of the VaultCore contract.
_srcToken
address
Source/Input token.
_dstToken
address
Destination/Output token.
_amountIn
uint256
Input token amount.
_minAmountOut
uint256
Minimum output tokens expected.
_receiver
address
Receiver of the tokens.
_token
address
Address of token to mint USDs with
_srcToken
address
Input token address.
_dstToken
address
Output token address.
_amountIn
uint256
Input amount of _srcToken.
uint256
Estimated output token amount.
_veSpaRewarder
address
Rewarder's address
_rewardPercentage
uint256
Percentage of SPA to be rewarded
_token
address
Address of the asset to be withdrawn
_receiver
address
Address of the receiver of tokens
_amount
uint256
Amount of tokens to be withdrawn
_newRewardPercentage
uint256
New Reward Percentage
_newVeSpaRewarder
address
is the address of desired veSpaRewarder
_newOracle
address
is the address of desired oracle
_spaIn
uint256
Amount of SPA tokens
_minUSDsOut
uint256
Minimum amount out in USDs
_usdsAmount
uint256
USDs amount the user wants
uint256
Amount of SPA required
_receiver
address
Receiver of USDs
_spaIn
uint256
Amount of SPA tokens
_minUSDsOut
uint256
Minimum amount out in USDs
_spaIn
uint256
Amount of SPA tokens
uint256
Amount of USDs user will get
_spaIn
uint256
Amount of SPA tokens
uint256
Amount of USDs user will get
uint256
uint256
The price of USDS in SPA, the price of SPA in USDS, and their respective precisions.
uint256
uint256
uint256
_rewardPercentage
uint256
The reward percentage to validate.
Inherits: IFarmRegistry, OwnableUpgradeable
Author: Sperax Foundation.
This contract tracks fee details, privileged users, deployed farms and farm deployers.
constructor
Parameters
_feeReceiver
address
Receiver of the fees.
_feeToken
address
The fee token for farm creation.
_feeAmount
uint256
The fee amount to be paid by the creator.
_extensionFeePerDay
uint256
Extension fee per day.
Register a farm created by registered Deployer.
Only registered deployer can register a farm.
Parameters
_farm
address
Address of the created farm contract
_creator
address
Address of the farm creator.
Register a new farm deployer.
Only owner can call this function.
Parameters
_deployer
address
Address of deployer to be registered.
Remove an existing deployer from registry.
Only owner can call this function.
Parameters
_id
uint16
ID of the deployer to be removed (0 index based).
Function to add/remove privileged User.
Only callable by the owner.
Parameters
_user
address
User Address for which privilege is to be updated.
_privilege
bool
Privilege(bool) whether true or false.
Get list of registered deployer.
Returns
<none>
address[]
Returns array of registered deployer addresses.
Get list of farms created via registered deployer.
Returns
<none>
address[]
Returns array of farm addresses.
Get all the fee parameters for creating farm.
It returns fee amount and extension fee as 0 if _user is privileged.
Parameters
_user
address
The account creating the farm.
Returns
<none>
address
Receiver of the fees.
<none>
address
Token in which fee is to be paid.
<none>
uint256
Amount of fees to be paid for creation of farm.
<none>
uint256
Extension fee per day in case of extending a farm.
Update the fee params for registry.
Parameters
_receiver
address
FeeReceiver address.
_feeToken
address
Token address for fee.
_amount
uint256
Amount of token to be collected.
_extensionFeePerDay
uint256
Extension fee per day.
Validate address.
Inherits: Ownable, ReentrancyGuard
Author: Sperax Foundation.
Exposes base functionalities which will be useful in every deployer.
Constructor.
Parameters
_farmRegistry
address
Address of the Demeter Farm Registry.
_farmId
string
Id of the farm.
Update farm implementation's address.
Only callable by the owner.
Ensure that _newFarmId
is correct for the new farm implementation.
Parameters
_newFarmImplementation
address
New farm implementation's address.
_newFarmId
string
ID of the new farm.
Collect fee and transfer it to feeReceiver.
Function fetches all the fee params from farmRegistry.
Validate address.
Inherits: FarmDeployer
Author: Sperax Foundation.
This contract allows anyone to calculate fees, pay fees and create farms.
Constructor of the contract.
Parameters
_farmRegistry
address
Address of the Demeter Farm Registry.
_farmId
string
Id of the farm.
_camelotV3Factory
address
Address of CamelotV3 factory.
_nfpm
address
Address of Camelot NonfungiblePositionManager contract.
_camelotUtils
address
Address of CamelotUtils (Camelot helper) contract.
_nfpmUtils
address
Address of Camelot INonfungiblePositionManagerUtils (NonfungiblePositionManager helper) contract.
Deploys a new CamelotV3 farm.
The caller of this function should approve feeAmount to this contract before calling this function.
Parameters
_data
FarmData
Data for deployment.
Returns
<none>
address
Address of the deployed farm.
Inherits: FarmStorage, OwnableUpgradeable, ReentrancyGuardUpgradeable, MulticallUpgradeable
Author: Sperax Foundation.
This contract contains the core logic for the Demeter farms.
Function to be called to withdraw deposit.
Parameters
_depositId
uint256
The id of the deposit.
A function to be called by the depositor to claim rewards.
Parameters
_depositId
uint256
The id of the deposit.
Function to be called to initiate cooldown for a staked deposit.
_depositId is corresponding to the user's deposit.
Parameters
_depositId
uint256
The id of the deposit to be locked.
Add rewards to the farm.
Parameters
_rwdToken
address
The reward token's address.
_amount
uint256
The amount of reward tokens to add.
Update the cooldown period.
Parameters
_newCooldownPeriod
uint256
The new cooldown period (in days). E.g: 7 means 7 days.
Pause / UnPause the farm.
Parameters
_isPaused
bool
Desired state of the farm (true to pause the farm).
A function to explicitly close the farm.
Recovers remaining non accrued rewards.
Recover erc20 tokens other than the reward tokens.
Parameters
_token
address
Address of token to be recovered.
Get the remaining reward balance out of the farm.
Function recovers minOf(_amount, rewardsLeft).
Parameters
_rwdToken
address
The reward token's address.
_amount
uint256
The amount of the reward tokens to be withdrawn.
Function to update reward params for a fund.
Parameters
_rwdToken
address
The reward token's address.
_newRewardRates
uint128[]
The new reward rate for the fund (includes the precision).
Transfer the tokenManagerRole to other user.
Only the existing tokenManager for a reward can call this function.
Parameters
_rwdToken
address
The reward token's address.
_newTknManager
address
Address of the new token manager.
Function to compute the total accrued rewards for a deposit for each subscription.
Parameters
_account
address
The user's address.
_depositId
uint256
The id of the deposit.
Returns
rewards
uint256[][]
The total accrued rewards for the deposit for each subscription (uint256[][]).
Get the reward fund details.
Returns
<none>
RewardFund[]
The available reward funds' details for all the reward funds.
Get the reward details for specified reward token.
Parameters
_rwdToken
address
The address of the reward token.
Returns
<none>
RewardData
The available reward details for the specified reward token.
Get deposit info for a deposit id.
Parameters
_depositId
uint256
The id of the deposit.
Returns
<none>
Deposit
The deposit info (Deposit).
Get number of subscriptions for an account.
Parameters
_depositId
uint256
The deposit id.
Returns
<none>
uint256
The number of subscriptions for the deposit.
Get subscription stats for a deposit.
Parameters
_depositId
uint256
The deposit id.
_subscriptionId
uint256
The subscription's id.
Returns
<none>
Subscription
The subscription info (Subscription).
Get reward rates for a rewardToken.
Parameters
_rwdToken
address
The reward token's address.
Returns
<none>
uint256[]
The reward rates for the reward token (uint256[]).
Get farm reward fund info.
Parameters
_fundId
uint8
The fund's id.
Returns
<none>
RewardFund
The reward fund info (RewardFund).
Function to get the reward tokens added in the farm.
Returns
<none>
address[]
The reward tokens added in the farm.
Function to be called by Demeter Rewarder to get tokens and amounts associated with the farm's liquidity.
This function should be overridden to add the respective logic.
Returns
<none>
address[]
Tokens associated with the farm's pool.
<none>
uint256[]
Amounts associated with the farm's liquidity.
Function to update the FarmRewardData for all funds.
Claim rewards and send it to another account.
Only the depositor can call this function.
Parameters
_account
address
To receive the rewards.
_depositId
uint256
The id of the deposit.
Update the farm start time.
Can be updated only before the farm start. New start time should be in future.
Parameters
_newStartTime
uint256
The new farm start time.
Returns if farm is open. Farm is open if it is not closed.
This function can be overridden to add any new/additional logic.
Returns
<none>
bool
bool True if farm is open.
Returns if farm is active. Farm is active if it is not paused and not closed.
This function can be overridden to add any new/additional logic.
Returns
<none>
bool
bool True if farm is active.
Get the reward balance for specified reward token.
This function calculates the available reward balance by considering the accrued rewards and the token supply.
Parameters
_rwdToken
address
The address of the reward token.
Returns
<none>
uint256
The available reward balance for the specified reward token.
Common logic for deposit in the demeter farm.
Parameters
_account
address
Address of the depositor.
_lockup
bool
Lockup option for the deposit.
_liquidity
uint256
Liquidity amount to be added to the pool.
Returns
<none>
uint256
The deposit id.
Common logic for initiating cooldown.
Parameters
_depositId
uint256
User's deposit Id.
Common logic for withdraw.
Parameters
_depositId
uint256
User's deposit id.
Claim rewards for the user.
NOTE: any function calling this private function should be marked as non-reentrant.
Parameters
_depositId
uint256
The id of the deposit.
Claim rewards for the user and send it to another account.
NOTE: any function calling this private function should be marked as non-reentrant.
Parameters
_depositId
uint256
The id of the deposit.
_receiver
address
The receiver of the rewards (Could be different from depositor)
Get the remaining reward balance out of the farm.
Function recovers minOf(_amount, rewardsLeft).
In case of partial withdraw of funds, the reward rate has to be set manually again.
Parameters
_rwdToken
address
The reward token's address.
_amount
uint256
The amount of the reward token to be withdrawn.
Function to update reward params for a fund.
Parameters
_rwdToken
address
The reward token's address.
_newRewardRates
uint128[]
The new reward rate for the fund (includes the precision).
Function to setup the reward funds and initialize the farm global params during construction.
Parameters
_farmId
string
ID of the farm. E.g: Demeter_Camelot_V2
.
_farmStartTime
uint256
- Farm start time.
_cooldownPeriod
uint256
- Cooldown period in days for locked deposits. E.g: 7 means 7 days.
_rwdTokenData
RewardTokenData[]
- Reward data for each reward token.
Adds new reward token to the farm.
Parameters
_token
address
Address of the reward token to be added.
_tknManager
address
Address of the reward token Manager.
Update the last reward accrual time.
Computes the accrued reward for a given fund id and time interval.
_alreadyAccRewardBal
is useful when this function called from computeRewards
function. As computeReward
is a view function and it doesn't update the accRewardBal
in the rewardData
.
Parameters
_rwdId
uint8
Id of the reward token.
_fundId
uint8
Id of the reward fund.
_time
uint256
Time interval for the reward computation.
_alreadyAccRewardBal
uint256
Already accrued reward balance.
Returns
<none>
uint256
accRewards Accrued rewards for the given _rwdId
, _fundId
and _time
.
Validate the deposit for account.
Parameters
_account
address
Address of the caller to be checked against depositor.
_depositId
uint256
Id of the deposit.
A function to validate deposit ts to prevent flash loan vulnerabilities
Reverts when deposit made in the same transaction.
Parameters
_depositTs
uint256
depositTs of user's deposit. (It represents deposit ts or increaseDeposit ts)
Validate if farm is open. Revert otherwise.
This function can be overridden to add any new/additional logic.
Validate if farm is active. Revert otherwise. Farm is active if it is not paused and not closed.
This function can be overridden to add any new/additional logic.
Validate the caller is the token Manager. Revert otherwise.
Parameters
_rwdToken
address
Address of reward token.
Validate the reward token is valid.
Parameters
_rwdToken
address
Address of reward token.
Get the time elapsed since the last reward accrual.
Returns
<none>
uint256
time The time elapsed since the last reward accrual.
An internal function to validate cooldown period.
Parameters
_cooldownPeriod
uint256
Period to be validated.
Validate address.
Parameters
_addr
address
Address to be validated.
Add subscription to the reward fund for a deposit.
Parameters
_fundId
uint8
The reward fund id.
_depositId
uint256
The unique ID of the deposit.
_liquidity
uint256
The liquidity of the deposit.
Unsubscribe a reward fund from a deposit.
The rewards claimed from the reward fund is persisted in the event.
Parameters
_fundId
uint8
The reward fund id.
_depositId
uint256
The deposit id corresponding to the user.
Pools in camelot V3 are very similar to Uniswap V3. When a liquidity provider supplies assets to the pool, the LP receives an NFT position in return.
Next, you can see the specification for Camelot V3 farm and Camelot V3 farm deployer.
Inherits: Farm, IERC721Receiver
Author: Sperax Foundation.
This contract contains the core logic for E721 farms.
Function is called when user transfers the NFT to this farm.
Parameters
<none>
address
_from
address
The address of the owner.
_tokenId
uint256
NFT Id generated by other protocol (e.g. Camelot or Uniswap).
_data
bytes
The data should be the lockup flag (bool).
Returns
<none>
bytes4
bytes4 The onERC721Received selector.
Function to withdraw a deposit from the farm.
Parameters
_depositId
uint256
The id of the deposit to be withdrawn.
Function to get the liquidity. Must be defined by the farm.
This function should be overridden to add the respective logic.
Parameters
_tokenId
uint256
The nft tokenId.
Returns
<none>
uint256
The liquidity of the nft position.
Inherits: IFarm
Author: Sperax Foundation.
This contract contains the base storage variables for farms.
Inherits: E721Farm, OperableDeposit, ClaimableFee
Author: Sperax Foundation.
This contract is the implementation of the Camelot V3 farm.
Initializer function of this farm.
Parameters
_input
InitializeInput
A struct having all the input params.
Allow user to increase liquidity for a deposit.
Parameters
_depositId
uint256
The id of the deposit to be increased.
_amounts
uint256[2]
Desired amount of tokens to be increased.
_minAmounts
uint256[2]
Minimum amount of tokens to be added as liquidity.
Withdraw liquidity partially from an existing deposit.
Parameters
_depositId
uint256
Deposit index for the user.
_liquidityToWithdraw
uint128
Amount to be withdrawn.
_minAmounts
uint256[2]
Minimum amount of tokens to be received.
Function to be called by Demeter Rewarder to get tokens and amounts associated with the farm's liquidity.
Returns
<none>
address[]
tokens An array of token addresses.
<none>
uint256[]
amounts An array of token amounts.
Claim pool fee implementation from ClaimableFee
feature.
Parameters
_depositId
uint256
Deposit ID of the deposit in the farm.
Validate the position for the pool and get Liquidity.
The position must adhere to the price ranges.
Only allow specific pool token to be staked.
Parameters
_tokenId
uint256
The tokenId of the position.
Returns
<none>
uint256
The liquidity of the position.
Validate the ticks (upper and lower).
Get the info of the required token.
Check if the token belongs to correct pool.
Check if the token adheres to the tick range.
The ticks must be within the max range and must be multiple of tickSpacing.
Parameters
_tickLower
int24
The lower tick of the range.
_tickUpper
int24
The upper tick of the range.
Inherits: IRewarderFactory, Ownable
Author: Sperax Foundation.
This contract deploys new rewarders and keeps track of them.
Constructor.
Parameters
_oracle
address
Address of the master price oracle of USDs.
Function to deploy new rewarder.
Parameters
_rwdToken
address
Address of the reward token for which the rewarder is to be deployed.
Returns
rewarder
address
Rewarder's address.
Update rewarder implementation's address
Parameters
_newRewarderImplementation
address
New Rewarder Implementation
Function to update the oracle's address.
Parameters
_newOracle
address
Address of the new oracle.
Validate address.
Parameters
_addr
address
Address to be validated.
Inherits: IRewarder, OwnableUpgradeable, ReentrancyGuardUpgradeable
Author: Sperax Foundation.
This contract tracks farms, their APR and other data for a specific reward token.
Farms for UniV3 pools using Rewarder contract must have a minimum observationCardinality of 20. It can be updated by calling increaseObservationCardinalityNext function on the pool.
Initializer function of this contract.
Parameters
_rwdToken
address
Address of the reward token.
_oracle
address
Address of the USDs Master Price Oracle.
_admin
address
Admin/ deployer of this contract.
Function to calibrate rewards for this rewarder's reward token for a farm.
Calculates based on APR, caps based on maxRewardPerSec or balance rewards, sends and sets the rewardRate in the farm.
Parameters
_farm
address
Address of the farm for which the rewards are to be calibrated.
Returns
rewardsToSend
uint256
Rewards which are sent to the farm.
Function to update the token manager's address in the farm.
Parameters
_farm
address
Farm's address in which the token manager is to be updated.
_newManager
address
Address of the new token manager.
Function to recover reward funds from the farm.
Parameters
_farm
address
Farm's address from which reward funds is to be recovered.
_amount
uint256
Amount which is to be recovered.
Function to update APR.
Parameters
_farm
address
Address of the farm.
_apr
uint256
APR in 1e8 precision.
Function to toggle calibration restriction.
Parameters
_farm
address
Address of farm for which calibration restriction is to be toggled.
Function to recover ERC20 tokens from this contract.
Parameters
_token
address
Address of the token.
_amount
uint256
Amount of the tokens.
Function to get token amounts value of underlying pool of the farm.
Parameters
_farm
address
Address of the farm.
Returns
<none>
address[]
Array of token addresses.
<none>
uint256[]
Function to get reward config for a farm.
Parameters
_farm
address
Address of the farm.
Returns
<none>
FarmRewardConfig
FarmRewardConfig Farm reward config.
Function to calculate the time till which rewards are there for an LP.
Parameters
_farm
address
Address of the farm for which the end time is to be calculated.
Returns
rewardsEndingOn
uint256
Timestamp in seconds till which the rewards are there in farm and in rewarder.
Function to update the REWARD_TOKEN configuration. This function calibrates reward so token manager must be updated to address of this contract in the farm.
Parameters
_farm
address
Address of the farm for which the config is to be updated.
_rewardConfig
FarmRewardConfigInput
The config which is to be set.
Internal initialize function.
Parameters
_rwdToken
address
Address of the reward token.
_oracle
address
Address of the USDs Master Price Oracle.
_admin
address
Admin/ deployer of this contract.
_rewarderFactory
address
Address of Rewarder factory contract.
Function to check if the farm's reward is configured.
Parameters
_farm
address
Address of the farm.
An internal function to get token amounts for the farm.
Parameters
_farm
address
Address of the farm.
Returns
<none>
address[]
Array of token addresses.
<none>
uint256[]
Array of token amounts.
Function to check if the reward token of this contract is one of farm's reward token.
Parameters
_farm
address
Address of the farm.
Returns
<none>
bool
If farm has one of the reward token as reward token of this contract.
Validate address.
Parameters
_addr
address
Address to be validated.
Function to set reward rate in the farm.
Parameters
_farm
address
Address of the farm.
_rwdRate
uint128
Reward per second to be emitted.
_nonLockupRewardPer
uint256
Reward percentage to be allocated to no lockup fund.
Function to adjust global rewards per second emitted for a reward token.
Parameters
_oldRewardRate
uint256
Old emission rate.
_newRewardRate
uint256
New emission rate.
Function to validate farm.
It checks that the farm should implement getTokenAmounts and have REWARD_TOKEN. as one of the reward tokens.
Parameters
_farm
address
Address of the farm to be validated.
_baseTokens
address[]
Array of base tokens.
Returns
<none>
bool
bool True if farm is valid.
Function to check whether the base tokens are a subset of farm's assets.
It handles repeated base tokens as well and pushes indexed in farmRewardConfigs.
Parameters
_farm
address
Address of the farm.
_baseTokens
address[]
Array of base token addresses to be considered for value calculation.
Returns
<none>
bool
hasBaseTokens True if baseTokens are non redundant and are a subset of assets.
Function to normalize asset amounts to be of precision REWARD_TOKEN_DECIMALS.
Parameters
_token
address
Address of the asset token.
_amount
uint256
Amount of the token.
Returns
<none>
uint256
Normalized amount of the token in _desiredPrecision.
Function to fetch and get the price of a token.
Parameters
_token
address
Token for which the the price is to be fetched.
_oracle
address
Address of the oracle contract.
Returns
priceData
IOracle.PriceData
Price data of the token.
Function to validate price feed.
Parameters
_token
address
Token to be validated.
_oracle
address
Address of the oracle.
Function to validate the no lockup fund's reward percentage.
Parameters
_percentage
uint256
No lockup fund's reward percentage to be validated.
Rewarder is a contract which can be used by farm admins when they want to emit rewards in fixed APR instead of fixed token amounts (by setting reward rate).
Inherits: Farm
Author: Sperax Foundation.
Farms build for pairs/ pools in which fee can be claimed can extend and override _claimPoolFee function of this contract.
A function to claim the pool fee earned by lp.
Only the deposit owner can call this function.
Parameters
_depositId
uint256
ID of the deposit.
Claim pool fee internal logic to be implemented by child farm contract.
Just override this function and write the logic to claim fee, validation and other checks are handled in claimPoolFee
.
Parameters
_depositId
uint256
Deposit ID of the deposit in the farm.
Returns
tokenId
uint256
Token ID of the deposit for E721 farms, for other farms return depositId.
amt0Recv
uint256
Amount 0 received as fee.
amt1Recv
uint256
Amount 1 received as fee.
Inherits: Farm
Author: Sperax Foundation.
This contract helps in creating farms with expiry feature.
Update the farm end time.
Can be updated only before the farm expired or closed. Extension should be incremented in multiples of 1 USDs/day with minimum of 100 days at a time and a maximum of 300 days. Extension is possible only after farm started.
Parameters
_extensionDays
uint256
The number of days to extend the farm. Example: 150 means 150 days.
Update the farm start time.
Can be updated only before the farm start. New start time should be in future. Adjusts the farm end time accordingly.
Parameters
_newStartTime
uint256
The new farm start time.
Returns bool status if farm is open. Farm is open if it is not closed and not expired.
Returns
<none>
bool
bool True if farm is open.
Setup the farm data for farm expiry.
Parameters
_farmStartTime
uint256
Start time of the farm.
_farmRegistry
address
Address of the farm registry.
Collects farm extension fee and transfers it to feeReceiver.
Function fetches all the fee params from farmRegistry.
Parameters
_extensionDays
uint256
The number of days to extend the farm. Example: 150 means 150 days.
Inherits: Farm
Author: Sperax Foundation.
This contract helps in creating farms with increase/decrease deposit functionality.
Update subscription data of a deposit for increase in liquidity.
Parameters
_depositId
uint256
Unique deposit id for the deposit.
_amount
uint256
_amount to be increased.
Update subscription data of a deposit after decrease in liquidity.
Parameters
_depositId
uint256
Unique deposit id for the deposit
_amount
uint256
_amount to be decreased.
Common logic for increasing a deposit.
Parameters
_depositId
uint256
Unique deposit id for the deposit
_amount
uint256
_amount to be decreased.
Common logic for decreasing a deposit.
Parameters
_depositId
uint256
Unique deposit id for the deposit
_amount
uint256
_amount to be decreased.
Users can mint USDs from their collateral (USDC.e, USDC, Frax, DAI, USDT or LUSD). The Mint page will automatically reflect the amount of collateral and SPA required to mint USDs (Currently, no SPA required). Users can redeem USDs for a collateral of their choice.
To mint USDs, you will need eligible collateral.
On the home page, enter the amount of collateral you would like to deposit The relationship value will automatically populate, and you can see how much USDs you will mint.
Approve Spend and Confirm the mint in your wallet.
On the home page, enter the amount of USDs you would like to redeem. The value of redeemed collateral will automatically populate depending on market conditions.
Approve Spend and Confirm the redemption in your wallet.
USDs L2 (Arbitrum) address: 0xD74f5255D557944cf7Dd0E45FF521520002D5748
SPA L2 address: 0x5575552988A3A80504bBaeB1311674fCFd40aD4B
SPA L1 address: 0xB4A3B0Faf0Ab53df58001804DdA5Bfc6a3D59008
wSPA L1 address: 0x2a95FE4c7e64e09856989F9eA0b57B9AB5f770CB
xSPA L2 address: 0x0966E72256d6055145902F72F9D3B6a194B9cCc3
Proxy contract deployed at: 0x2e2071180682Ce6C247B1eF93d382D509F5F6A17
Implementation contract deployed at: 0xD16f5343FDDD2DcF6A8791e302A204c13069D165
Proxy contract deployed at: 0xbF82a3212e13b2d407D10f5107b5C8404dE7F403
Implementation contract deployed at: 0xA3F8745548A98ee67545Abcb0Cc8ED3129b8fF8D
veSPA holders will deliberate on protocol governance
Sperax has launched its off-chain governance process. On-chain governance protocol will be launched next. Through governance, community can make changes to the USDs protocol parameters, bring in new partnerships, new yield opportunities etc.
Ideation Flow:
Start a conversation in the official governance channel in Discord.
Gather feedback from the community.
(Optional) Create a poll on discord to gauge community sentiment.
(Optional) If you’d like to talk about your idea on a Sperax Community Call, feel free to contact a team member via Discord to coordinate.
Make sure to add the correct tag to the proposal(see below for definitions):
USDs parameter: Proposals related to adjusting/modifying USDs components.
New Assets and Yield Strategies: Proposals related to adding new forms of collateral and yield strategy schemes/methodologies.
Liquidity Mining: Proposals related to the improvement of Sperax farming & liquidity mining mechanisms.
Product Feature: Proposals related to the improvement, addition, or modification of new & existing Sperax products.
Partnership(s): Proposals related to inquiring & establishing potential partnerships with the Sperax Protocol.
Other: Miscellaneous proposals that have yet to be assigned a defined tag/category.
All snapshot polls will last 3 days upon initiation. Votes will be weighed by the voters' veSPA balance. A snapshot poll will include 2 vote options (Yes/ No) by default. If proposal creator wants 3 vote options (Yes/ No/ Yes with modification) then they can inform that to the moderators while snapshot poll is created. If 'Yes with modification' option gets max votes, then the proposal is not subject to cooldown period.
Proposal Passing Criteria:
Acceptance Threshold: Proposal must receive more than 50% in "Yes" votes
Minimum Quorum: At least 200 Million veSPA should vote in the snapshot poll
Possible outcomes at this stage:
Both the proposal passing criteria are met: the proposal passes and escalates to a Sperax Improvement Plan (SIP).
Quorum is not met: The proposal does not meet minimum quorum and is marked “Defeated” by the moderators. The proposal undergoes a 7-day cooldown period. At the conclusion of this period, the proposer can resubmit the proposal and proceed with the governance process.
Quorum is met but does not receive more than 50% in 'Yes' votes: The post is marked as ‘Defeated’ by the moderators.
If “No” votes > “Yes with modification” votes - The proposal must then undergo a 7-day cooldown period. Afterward, the proposer must then resubmit the proposal, along with any necessary modifications, and proceed with the governance process.
If “Yes with modification” votes >= “No” votes - The proposal can be returned to the deliberation phase for modifications and is not subject to the 7-day cooldown period. Once modifications are made to the proposal it can be elevated to a Snapshot vote once again.
When a governance proposal passes the snapshot vote in the previous stage, the proposal moves to Sperax Improvement Plan. This will have the list of all accepted proposals. The Sperax engineering team will pick up proposals from SIP for implementation based on their priorities and bandwidth. Community can also help write the code for implementing proposals from SIP. All codes will have to be audited before implementation. Sperax Foundation will help in facilitating the audits.
Check the repository of all the winning proposals
Track the implementation of these proposals
Choose amount of SPA you want to stake, lockup period and you can check veSPA balance corresponding to that
Select cooldown type to choose between auto-cooldown or stay staked at residual balance
Click on Stake to stake your SPA
Once the transaction is processed, you can see your
veSPA balance
SPA staked
Expiry date
Button to extend lockup period
Click on the 'Extend Lockup' button
Select how much you want to extend your lockup period. You can see the updated expiry date and veSPA balance
Click on Extend Lockup
Select additional amount of SPA tokens you want to stake
You can see veSPA balance corresponding the same lockup as your existing veSPA balance.
Click on Stake to stake additional amount of SPA. The new veSPA balance will also expire at the same time as the previous balance.
Though all the Sperax and SPA functionality lives on Arbitrum now - it might happen that some early users still have SPA on the chain Sperax started with - Ethereum.
From today's perspective, SPA held on Ethereum can be used only for transfers between on-chain accounts or for depositing SPA to CEXs supporting SPA deposits on Ethereum. SPA on Ethereum can't be used for staking, yield farming (Farms on Sperax DApp), or for voting on Snapshot.
If you still have SPA on Ethereum Mainnet, you need to bridge it from Ethereum to Arbitrum in order to unlock SPA potential in DeFi.
The Arbitrum bridge accepts a wrapped form of SPA (wSPA), so first of all you must wrap your SPA on Ethereum in order to bridge it. Don’t worry, the value of your tokens will not change.
Below you can find instructions for transferring SPA to Arbitrum. Please make sure you have some ETH in your wallet to manage gas fees when wrapping and bridging SPA. Please remember: wSPA has no other function except being an intermediary token for bridging. Please don't try to send wSPA to any CEX or sell it - the transaction may fail or you can lose your tokens. Use wSPA only to bridge it to Arbitrum and get your SPA on Arbitrum.
Step 1: SPA (Ethereum Mainnet) → wSPA (Ethereum Mainnet)
Connect to Ethereum mainnet using your wallet using the appropriate provider.
Enter the amount of SPA you want to convert to wSPA. Note that 1 SPA = 1 wSPA.
Then click on 'Swap', provide consent and send the transaction.
You can now see the wSPA tokens in your wallet.
Step 2: wSPA (Ethereum Mainnet) → SPA (Arbitrum)
Connect your wallet using the appropriate provider.
Select wSPA token by pasting its token address: (0x2a95FE4c7e64e09856989F9eA0b57B9AB5f770CB)
Enter the amount of wSPA that you want to bridge. You will receive the same amount of SPA on Arbitrum. (Note that the website may show that you will receive wSPA, but be assured that you will receive SPA on Arbitrum. You can verify that using SPA Arbitrum's token address: 0x5575552988A3A80504bBaeB1311674fCFd40aD4B)
Click on 'Move funds to Arbitrum One' and then send the transaction to give permission to transfer the capped amount of wSPA.
Send the transaction now to bridge and wait for some time for the transcation to be completed successfully.
You can track the transaction status/history on the bridge page. In some time, you should see the SPA tokens on Arbitrum in your wallet.
xSPA is a reward token of the Sperax ecosystem. xSPA can be either staked for veSPA with a lockup of 180 days or more, or redeemed within 15 to 180 days giving 50% to 100% SPA upon redemption.
Since the start of SPA Gauge, USDs total supply has decreased from $2M to $1.78M. In the meantime, SPA Gauge has emitted about 80M SPA amounting to $392K. The SPA circulating supply has increased from 1.593B to 1.658B.
Emitting SPA in a predetermined manner and without assessing the market dynamics is improper utilization of resources. Since our target is to increase USDs adoption which will help in growing the Sperax ecosystem and its participants, we must rethink our overall strategy.
Apart from maintaining the target to make SPA deflationary, SperaxDAO should ensure that the emission is invested back into the ecosystem and contributes directly towards increasing the USDs adoption and supply.
All SPA emissions should have a looping effect such that a good portion of SPA distributed should be invested back into the ecosystem in the form of veSPA and increase the burning rate of SPA. Since the emissions are not helping in increasing either USDs adoption or the locked tokens. The recent increment in veSPA numbers is primarily driven by the team token allocation in veSPA. The Sperax ecosystem is steadily moving towards complete decentralization of protocols and hence should have more governance participation.
The Sperax ecosystem should have a new reward token. A token which can be staked as veSPA or redeemed for SPA. After drawing some inspiration from the Camelot emission strategy, the core team proposes the launch of a new token called xSPA. Users can either stake 1 xSPA for one veSPA or redeem 1 xSPA for 1 SPA.
Users can redeem 1 xSPA token for SPA by depositing their xSPA token through the redemption contract. Users can stake 1 xSPA in veSPA to increase their staked SPA balance. The relation between xSPA, SPA, and veSPA will be governed by the following rules
1 xSPA will be equivalent to 1 SPA.
Users can redeem 1 xSPA for 1 SPA if they lock the xSPA in the redemption contract for 180 days, the maximum redemption period.
Users can redeem 1 xSPA for 0.5 SPA if they lock the xSPA in the redemption contract of 15 days, the minimum redemption period.
If the redemption period is ‘x’, between 15 and 180 days, the amount of SPA a user gets is governed by the following equation:
Receivable spaAmount = (_xSpaAmount * (_redeemDuration + 150 days)) / 330 days
A redemption request cannot be modified or canceled.
The redemption contract will instantly burn any differential SPA
In case of the minimum locking period of 15 days, half the SPA tokens will be burnt right away and users can claim their SPA tokens after 15 days.
In case of a maximum locking period of 180 days, no SPA will be burnt and users can claim their SPA token after 180 days.
In case of a period between 15 and 180 days, SPA burnt is:
SpaBurnt = _xSpaAmount - Receivable spaAmount
Users can claim their SPA tokens after the locking period.
Users can stake 1 xSPA token in the veSPA contract to increase their staked SPA balance by 1 SPA token for the existing lockup period if the lockup period is greater than 180 days.
If the user has 0 staked balance, the system will throw an error and will ask the user to create a staked position with a minimum staking period of 180 days
If the user has staked balance but the lockup is less than 180 days, the system will throw an error and ask the user to increase the locking period to a minimum of 180 days
Users will be able to increase their staked position if the lockup period is above 180 days.
xSPA token is transferrable.
The staking and redemption criteria can be updated/modified through governance.
The minimum redemption period is 15 days in which you will receive only 100/2 = 50 SPA after 15 days.
The maximum redemption period is 180 days in which you will receive all your 100 SPA back for your 100 xSPA.
The Security of Sperax’s USDs and Demeter users is paramount. The engineering team and our auditors have invested significant time and resources to ensure that USDs and Demeter are secure and dependable. The USDs and Demeter smart contracts are publicly verifiable. The details and statistics of circulating supply, underlying collateral, collateral strategies, Farms etc are publicly available.
On 1st March 2024 we are launching our bug bounty program. Security researchers, fulfilling the eligibility criteria as mentioned in this document, are eligible for a bug bounty for reporting undiscovered vulnerabilities. The Program aims to incentivize responsible disclosure and enhance the security of the USDs protocol and Demeter.
Security is one of our core values. We value the input of hackers acting in good faith to help us maintain the highest standard for the security and safety of the Sperax ecosystem. The USDs protocol and Demeter, while it has gone through a professional audit, depends on new technology that may contain undiscovered vulnerabilities.
The Sperax team encourages the community to audit our contracts and security. We also encourage the responsible disclosure of any issues. This program is intended to recognize the value of working with the community of independent security researchers. It sets out our definition of good faith in the context of finding and reporting vulnerabilities, as well as, what you can expect from us in return.
The following are not within the scope of the Program:
Bugs in any third-party contract or platform that interacts with USDs protocol;
Vulnerabilities related to domains, DNS, or servers of websites;
Vulnerabilities already reported or discovered in contracts built by third parties on USDs;
Any already-reported bugs or other vulnerabilities.
Test contracts and staging servers unless the discovered vulnerability also affects the USDs Protocol or could otherwise be exploited in a way that risks user funds.
To be eligible for a reward under this Program, you must:
Discover a previously unreported, non-public vulnerability within the scope of this Program. Vulnerabilities must be distinct from the issues covered in the previously conducted publicly available audits.
Include sufficient detail in your disclosure to enable our engineers to quickly reproduce, understand, and fix the vulnerability.
Be the first to disclose the unique vulnerability to the Team by the disclosure requirements below. If similar vulnerabilities are reported, the first submission shall be rewarded (if determined valid and otherwise in the scope of this Program)
Be reporting in an individual capacity, or if employed by a company, reporting with the company’s written approval to submit a disclosure to Sperax
Not be a current or former Sperax team member, vendor, contractor, or employee of a SperaxDAO vendor or contractor.
Not be subject to any international, national, or state-level sanctions.
Be at least 18 years of age or, if younger, submit your vulnerability with the consent of your parent or guardian.
Not exploit the vulnerability in any way, including by making it public or obtaining a profit (other than a reward under this Program). Any publicity in any way, whether direct or indirect, relating to any bug or vulnerability will automatically disqualify it and you from the Program.
To encourage vulnerability research and to avoid any confusion between good-faith hacking and malicious attacks, we require that you:
Play by the rules, including following the terms and conditions of this program and any other relevant agreements. If there is any inconsistency between this program and any other relevant agreements, the terms of this program will prevail.
Report any vulnerability you’ve discovered promptly.
Make a good faith effort to avoid privacy violations, data destruction, harming user experience, interruption, or degradation of the Sperax ecosystem and services.
Use only the google form to submit vulnerabilities with us.
Keep the details of any discovered vulnerabilities confidential until they are fixed.
Perform testing only on in-scope systems, and respect systems and activities which are out-of-scope.
Not submit a separate vulnerability caused by an underlying issue that is the same as an issue on which a reward has been paid under this Program.
Only interact with accounts you own or with explicit permission from the account holder.
Not engage in any unlawful conduct when disclosing the bug, including through threats, demands, or any other coercive tactics.
When working with us according to this program, you can expect us to:
Pay generous rewards for eligible discoveries based on the severity and exploitability of the discovery, at The Sperax team's sole discretion
Extend Safe Harbor for your vulnerability research related to this program, meaning we will not threaten or bring any legal action against anyone who makes a good faith effort to comply with our bug bounty program.
Work with you to understand and validate your report, including a timely initial response to the submission.
Work to remediate discovered vulnerabilities promptly.
Recognize your contribution to improving our security if you are the first to report a unique vulnerability, and your report triggers a code or configuration change.
All reward determinations, including eligibility and payment amount, are made at Sperax’s sole discretion. The Sperax team reserves the right to reject submissions and alter the terms and conditions of this program.
Sperax Treasury offers rewards for discoveries that can prevent the loss of assets, the freezing of assets, or harm to a user, commensurate with the severity and exploitability of the vulnerability. Sperax Treasury will pay a reward of $500 to $15,000 for eligible discoveries according to the terms and conditions provided below.
The Team evaluates all submissions on a case-by-case basis. Rewards are allocated based on the severity of the issue, and other variables, including, but not limited to a) the quality of the issue description, b) the instructions for reproducibility, and c) the quality of the fix (if included). A detailed report of a vulnerability increases the likelihood of a reward and may increase the reward amount. Therefore, please provide as much information about the vulnerability as possible.
The Program intends to follow a similar approach as the Ethereum Bug Bounty, where the severity of the issues will be based according to the OWASP risk rating model based on “Impact” and “Likelihood”. The evaluation of scoring is however at the sole discretion of the Sperax Team.
All rewards are paid in SPA and xSPA tokens with a 50-50 split (15-day TWAP) via a transfer to the wallet address provided by the participant to the Team. As a condition of participating in this Program, the participants give the Sperax Team permission to share their wallet addresses and other information provided by them to third parties to administer this Program and comply with applicable laws, regulations, and rules.
The reward will be received in SPA token based on the following severity scheme:
Note = Up to 100 US dollars
Very low = Up to 500 US dollars
Low = Up to 1,000 US dollars
Medium = Up to 2,500 US dollars
High = Up to 5,000 US dollars
Very High = Up to 10,000 US dollars
Critical = Up to 15,000 US dollars
The decisions made regarding rewards are final and binding.
By submitting your report, you grant the Company all rights, including without limitation intellectual property rights, needed to validate, mitigate, and disclose the vulnerability. All reward decisions, including eligibility for and amounts of the rewards and how such rewards will be paid, are made at the Company's sole discretion.
Terms and conditions of the Program may be altered at any time. The company may change or cancel this Program at any time, for any reason.
Token distribution schedule, details of tokens held by the foundation and community treasury
Circulating Supply = Total Supply of SPA on Ethereum + Total Supply of SPA on Arbitrum + Total Supply of wSPA on Ethereum - wSPA locked on Arbitrum bridge - SPA balance held by major wallets - SPA locked in SPA Staking Protocol
SPA token address (Ethereum): 0xb4a3b0faf0ab53df58001804dda5bfc6a3d59008
SPA token address (Arbitrum): 0x5575552988A3A80504bBaeB1311674fCFd40aD4B
wSPA (wrapped SPA) token address (Ethereum): 0x2a95FE4c7e64e09856989F9eA0b57B9AB5f770CB
Arbitrum bridge where wSPA is locked (Ethereum): 0xcEe284F754E854890e311e3280b767F80797180d
Tokens from Bootstrap Liquidity have been moved to a lot of Farm rewarder contracts and deployer wallet addresses for operational reasons. Please find below the list of those addresses. We will try our best to keep this list constantly updated.
FarmRegistry
RewarderFactory
CamelotV3Deployer
The Sperax DAO governance process primarily utilizes the Sperax DAO Governance . In order for a proposal to be accepted, it must go through the following phases:
If you have an idea you’d like to share, please feel free to post it in channel on Sperax Discord, or, if you prefer to submit a proposal, you can use the and submit your concept in the channel.
If you are ready to submit a formal proposal, you may do so on the channel using the . Here you’ll begin to receive constructive feedback from the community as well as the Sperax team. Discussion will continue for a minimum of 48 hours.
Once a proposal has gained traction, a snapshot poll will be created for voting. A Moderator will proceed to create the snapshot poll, link it to the corresponding forum post, and submit it on the channel on Forum. Votes can be cast directly through .
Visit the
Additionally, if your tokens do not appear after swapping or bridging, make sure you manually add to your wallet.
Open .
Import into your wallet using this token address: 0x2a95FE4c7e64e09856989F9eA0b57B9AB5f770CB
Navigate to . (Make sure that you are bridging from Ethereum to Arbitrum One.)
Earlier in 2023, SperaxDAO decided on the SPA budget for emission through Gauge () and redirecting veSPA emissions to bribes on Gauge (). Every week, Gauge emits 2.9 M SPA and veSPA voters are bribed 383K SPA. This SPA should be used more prominently and assertively to drive USDs growth and bring new adoption.
Allow xSPA token contract to transfer SPA from your account by calling function on token contract by passing spender as 0x0966E72256d6055145902F72F9D3B6a194B9cCc3
xSPA’s address and amount as the desired amount of xSPA you would like to have. Note: To allow 1 SPA pass 1000000000000000000 i.e 1e18 as amount in the approve function.
Call mint function on xSPA contract by passing the amount if you want to receive xSPA on your account or mint function by passing the address of the receiver account and amount if you want to receive the xSPA on another account.
Check your xSPA balance by calling function on by passing in your account’s address.
If you select any period between 15 days to 180 days, the SPA amount redeemed would be calculated on pro rata basis between 50% to 100% of SPA for your xSPA. You can get this amount by calling function on the xSPA contract by passing the xSPA amount with precision and your redeemDuration in seconds between 1296000 (15 days) to 15552000 (180 days) and it will return the SPA amount you will receive at the end of your redemption period.
To create a redemption request you can call on the xSPA contract by passing the xSPA amount with precision and the redeem duration between the range specified above. It returns the redemption request ID which will be used to track and claim later.
Once you have created a redemption request in the above step, you can see and track your redemption request by calling function on the xSPA contract by passing your redemption request ID, it returns the requester’s address, unlock time in unix epoch and spa amount which will be unlocked.
Once the current unix epoch time is more than the unlock time of the redemption request, you can call the function by passing in your redemption request ID if you want to receive the SPA tokens on your account otherwise you can call function by passing an address of another account as receiver and your request ID to send the SPA to another account.
For this redemption you must have an existing veSPA lock for at least 180 days or more, if you do not have, you can call function on the veSPA contract by passing the amount, lock duration (minimum 180 days) and auto cooldown preference.
If you have an active veSPA lock for at least 180 days or more, you can call function on the xSPA token contract and your veSPA balance would be increased immediately.
The Program includes the vulnerabilities and bugs in the USDs protocol core repository (located in the GitHub repositories, primarily at: and . This list may change as new contracts are deployed or existing contracts are removed from usage.
A researcher needs to submit all bug bounty disclosures to . The disclosure must include clear and concise steps to reproduce the discovered vulnerability in written or video format. The Sperax team will follow up promptly with acknowledgment of the disclosure.
The SPA that is bought back from the open markets using 50% of the auto-yield and 100% of the fees is stored in : (Arbitrum One) SPA circulating supply which is in Beta. It can be used to view the circulating supply breakdown for the token.
Almost certain
$1000
$2500
$5000
$10000
$15000
Likely
$500
$1000
$2500
$5000
$10000
Possible
$100
$500
$1000
$2500
$5000
Unlikely
$100
$100
$500
$1000
$2500
Almost Possible
$100
$100
$100
$500
$1000
Treasury
This vests linearly over a 4-year time-lock, beginning from the launch date of governance protocol. The DAO will control this fund and utilize for future partnerships, marketing incentives, liquidity mining rewards, etc.
1,250,000,000
25%
Foundation
Foundation funds are being used to make initial markets and for protocol development. Since the foundation lends the tokens to third parties for market making activities, the actual token balance held in the foundation wallet will fluctuate. Foundation has burnt 375MM SPA in 2022 to further decentralise the protocol - 250MM SPA in May and 125MM SPA in September. 0xC6e00e0E3544C93460cdFb53E85C4528EF348265 is an operator wallet which is sometimes used to move tokens from Layer 1 to Layer 2.
1,250,783,000
25.02%
Bootstrap Liquidity
This will be used to provide rewards for liquidity mining during protocol genesis. Future liquidity mining rewards will be funded from treasury funds
500,000,000
10%
Staking Rewards
This will be used to reward users who stake $SPA in the staking protocol. Stakers will earn fees from the minting and redeeming of $USDs, as well as staking rewards from the allocated rewards budget.
500,000,000
10%
Team & Advisor
This vests linearly over 4 years with a 6 month cliff. Token unlock schedule will start from 4/1/2022 for existing team members. For new members, vesting would start at least three months from the day they join.
499,217,000
9.98%
Private Sale
All SPA tokens have been vested under a strict vesting schedule of 1 year starting from 9/18/2021.
750,000,000
15%
veSPA L1
Ethereum
0xbF82a3212e13b2d407D10f5107b5C8404dE7F403
veSPA L2
Arbitrum
0x2e2071180682Ce6C247B1eF93d382D509F5F6A17
RewardDistributor L1
Ethereum
0xa61DD4480BE2582283Afa54E461A1d3643b36040
RewardDistributor L2
Arbitrum
0x2c07bc934974BbF413a4a4CeDA98713DCb8d9e16
Staking Reward
Arbitrum
0x3702E3e2DB2b5d037c1dbB23Ab7A51d0Cc90BD0e
Bootstrap Liquidity
Ethereum
0x8B65CE3b4Eaa8958346096C3a9303b73f2012aCc
Bootstrap liquidity deployer
Ethereum and Arbitrum
0xc28c6970D8A345988e8335b1C229dEA3c802e0a6
USDs/USDC Farm Rewarder (SPA)
Arbitrum
0x1733c5bc884090C73D89303467461693c54Ba58B
SPA/USDs Farm Rewarder 1 (SPA)
Arbitrum
0x136C218Ff8E87eD68f851433685960819F06b1fE
USDs/USDC Farm Vesting (SPA)
Arbitrum
0x638d76763dE9492b609b0d8830D8F626C5933A4D
SPA/USDs Farm Vesting (SPA)
Arbitrum
0x03b35477cFD400dEdfAc06f40422491500cbc663
SPA/USDs Farm Rewarder 2 (SPA)
Arbitrum
0x36033594EC23E0f0B187f767889Eb4C539F4aE03
SPA/USDs Farm Vesting 2 (SPA)
Arbitrum
0xC0F0484a216AfF20E0ead1a1513cE40fe0AFe0fe
SPA-Reserve-L2 multi-sig
Arbitrum
0xb56e5620A79cfe59aF7c0FcaE95aADbEA8ac32A1
SPA Farm
Arbitrum
SPA Farm rewarder
Arbitrum
Bootstrap liquidity Arbitrum
Arbitrum
0xAF64e027D42bAc1C14277fd295De9Ae318eEF17E