USDs
USDs
ERC20 contract
USDs is a stablecoin yield aggregator that provides 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 70% goes for USDs auto yield, and rest is used for SPA buyback and burn.
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.
Contract Documentation
Inherits: ERC20PermitUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable, IUSDs
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.
Inspired by OUSD: https://github.com/OriginProtocol/origindollar/blob/master/contracts/contracts/token/OUSD.sol
State Variables
MAX_SUPPLY
uint256 private constant MAX_SUPPLY = ~uint128(0);
_totalSupply
uint256 internal _totalSupply;
_deprecated_vars
uint256[4] private _deprecated_vars;
_allowances
mapping(address => mapping(address => uint256)) private _allowances;
vault
address public vault;
_creditBalances
mapping(address => uint256) private _creditBalances;
_deprecated_rebasingCredits
uint256 private _deprecated_rebasingCredits;
rebasingCreditsPerToken
uint256 public rebasingCreditsPerToken;
nonRebasingSupply
uint256 public nonRebasingSupply;
nonRebasingCreditsPerToken
mapping(address => uint256) public nonRebasingCreditsPerToken;
rebaseState
mapping(address => RebaseOptions) public rebaseState;
_deprecated_gatewayAddr
address[2] private _deprecated_gatewayAddr;
_deprecated_isUpgraded
mapping(address => bool) private _deprecated_isUpgraded;
paused
bool public paused;
Functions
onlyVault
Verifies that the caller is the Savings Manager contract.
modifier onlyVault();
constructor
constructor();
initialize
Initializes the contract with the provided name, symbol, and vault address.
function initialize(string memory _nameArg, string memory _symbolArg, address _vaultAddress) external initializer;
Parameters
_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.
mint
Mints new USDs tokens, increasing totalSupply.
function mint(address _account, uint256 _amount) external override onlyVault nonReentrant;
Parameters
_account
address
The account address to which the newly minted USDs will be attributed.
_amount
uint256
The amount of USDs to be minted.
burn
Burns tokens, decreasing totalSupply.
function burn(uint256 _amount) external override nonReentrant;
Parameters
_amount
uint256
The amount to burn.
rebaseOptIn
Voluntary opt-in for rebase.
Useful for smart-contract wallets.
function rebaseOptIn() external;
rebaseOptOut
Voluntary opt-out from rebase.
function rebaseOptOut() external;
rebaseOptIn
Adds _account
to the rebasing account list.
function rebaseOptIn(address _account) external onlyOwner;
Parameters
_account
address
Address of the desired account.
rebaseOptOut
Adds _account
to the non-rebasing account list.
function rebaseOptOut(address _account) external onlyOwner;
Parameters
_account
address
Address of the desired account.
rebase
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.
function rebase(uint256 _rebaseAmt) external override onlyVault nonReentrant;
Parameters
_rebaseAmt
uint256
The amount of USDs to rebase with.
updateVault
Change the vault address.
function updateVault(address _newVault) external onlyOwner;
Parameters
_newVault
address
The new vault address.
pauseSwitch
Called by the owner to pause or unpause the contract.
function pauseSwitch(bool _pause) external onlyOwner;
Parameters
_pause
bool
The state of the pause switch.
transfer
Transfer tokens to a specified address.
function transfer(address _to, uint256 _value) public override returns (bool);
Parameters
_to
address
The address to transfer to.
_value
uint256
The amount to be transferred.
Returns
bool
True on success.
transferFrom
Transfer tokens from one address to another.
function transferFrom(address _from, address _to, uint256 _value) public override returns (bool);
Parameters
_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.
Returns
bool
true on success.
approve
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.
function approve(address _spender, uint256 _value) public override returns (bool);
Parameters
_spender
address
The address that will spend the funds.
_value
uint256
The amount of tokens to be spent.
Returns
bool
true on success.
increaseAllowance
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.
function increaseAllowance(address _spender, uint256 _addedValue) public override returns (bool);
Parameters
_spender
address
The address that will spend the funds.
_addedValue
uint256
The amount of tokens to increase the allowance by.
Returns
bool
true on success.
decreaseAllowance
Decrease the amount of tokens that an owner has allowed a _spender
to spend.
function decreaseAllowance(address _spender, uint256 _subtractedValue) public override returns (bool);
Parameters
_spender
address
The address that will spend the funds.
_subtractedValue
uint256
The amount of tokens to decrease the allowance by.
Returns
bool
true on success.
totalSupply
Check the current total supply of USDs.
function totalSupply() public view override(ERC20Upgradeable, IUSDs) returns (uint256);
Returns
uint256
The total supply of USDs.
balanceOf
Gets the USDs balance of the specified address.
function balanceOf(address _account) public view override returns (uint256);
Parameters
_account
address
The address to query the balance of.
Returns
uint256
A uint256 representing the amount of base units owned by the specified address.
creditsBalanceOf
Gets the credits balance of the specified address.
function creditsBalanceOf(address _account) public view returns (uint256, uint256);
Parameters
_account
address
The address to query the balance of.
Returns
uint256
(uint256, uint256) Credit balance and credits per token of the address.
uint256
allowance
Function to check the amount of tokens that an owner has allowed a spender.
function allowance(address _owner, address _spender) public view override returns (uint256);
Parameters
_owner
address
The address that owns the funds.
_spender
address
The address that will spend the funds.
Returns
uint256
The number of tokens still available for the spender.
_mint
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.
function _mint(address _account, uint256 _amount) internal override;
Parameters
_account
address
The account address to which the newly minted USDs will be attributed.
_amount
uint256
The amount of USDs that will be minted.
_burn
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.*
function _burn(address _account, uint256 _amount) internal override;
Parameters
_account
address
The account address from which the USDs will be burnt.
_amount
uint256
The amount of USDs that will be burnt.
_executeTransfer
For non-rebasing accounts credit amount = _amount
Update the count of non-rebasing credits in response to a transfer
function _executeTransfer(address _from, address _to, uint256 _value) private;
Parameters
_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
_rebaseOptIn
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.
function _rebaseOptIn(address _account) private;
Parameters
_account
address
address of the account opting in for rebase.
_rebaseOptOut
Remove a contract address from the non-rebasing exception list.
function _rebaseOptOut(address _account) private;
_isNonRebasingAccount
Is an account using rebasing accounting or non-rebasing accounting? Also, ensure contracts are non-rebasing if they have not opted in.
function _isNonRebasingAccount(address _account) private returns (bool);
Parameters
_account
address
Address of the account.
_ensureNonRebasingMigration
Ensures internal account for rebasing and non-rebasing credits and supply is updated following the deployment of frozen yield change.
function _ensureNonRebasingMigration(address _account) private;
Parameters
_account
address
Address of the account.
_balanceOf
Calculates the balance of the account.
Function assumes the _account is already upgraded.
function _balanceOf(address _account) private view returns (uint256);
Parameters
_account
address
Address of the account.
_creditsPerToken
Get the credits per token for an account. Returns a fixed amount if the account is non-rebasing.
function _creditsPerToken(address _account) private view returns (uint256);
Parameters
_account
address
Address of the account.
_isNotPaused
Validates if the contract is not paused.
function _isNotPaused() private view;
Events
TotalSupplyUpdated
event TotalSupplyUpdated(uint256 totalSupply, uint256 rebasingCredits, uint256 rebasingCreditsPerToken);
Paused
event Paused(bool isPaused);
VaultUpdated
event VaultUpdated(address newVault);
RebaseOptIn
event RebaseOptIn(address indexed account);
RebaseOptOut
event RebaseOptOut(address indexed account);
Errors
CallerNotVault
error CallerNotVault(address caller);
ContractPaused
error ContractPaused();
IsAlreadyRebasingAccount
error IsAlreadyRebasingAccount(address account);
IsAlreadyNonRebasingAccount
error IsAlreadyNonRebasingAccount(address account);
CannotIncreaseZeroSupply
error CannotIncreaseZeroSupply();
InvalidRebase
error InvalidRebase();
TransferToZeroAddr
error TransferToZeroAddr();
TransferGreaterThanBal
error TransferGreaterThanBal(uint256 val, uint256 bal);
MintToZeroAddr
error MintToZeroAddr();
MaxSupplyReached
error MaxSupplyReached(uint256 totalSupply);
Enums
RebaseOptions
enum RebaseOptions {
NotSet,
OptOut,
OptIn
}
Last updated
Was this helpful?