SMART Token

SmartToken

Git Source

Inherits: Initializable, UUPSUpgradeable, OwnableUpgradeable, ERC20Upgradeable, ERC20PermitUpgradeable, BaseContract, IERC4626Upgradeable, ReentrancyGuardUpgradeable, FlashloanSpecifics

This is a rebalancing token, part of Risk Protocol's system The same contract is used by both RiskON and RiskOFF Whenever a user deposit a unit of underlying in the Vault(TokenFactory), the user is expected to recieve a unit of both RiskON and RiskOFF. At every rebalance operation, the user RiskOn/OFF balances will be aligned with respect to the rebalance math.

State Variables

tokenFactory

The tokenFactory instance

TokenFactory private tokenFactory;

underlyingToken

The underlyingToken instance

IERC20Update private underlyingToken;

isX

bool private isX;

isNativeToken

bool private isNativeToken;

weth

IWETH private weth;

premiumDenominator

uint16 private constant premiumDenominator = 10000;

Functions

onlyTokenFactory

Ensures that the function is only callable by the TokenFactory contract. Calls the helper function _onlyTokenFactory to check the caller.

modifier onlyTokenFactory();

onlyAssetOwner

Ensures that the function is only callable by the token owner/holder. Calls the helper function _onlyAssetOwner to check the caller against the provided token owner/holder address.

modifier onlyAssetOwner(address assetOwner);

Parameters

Name
Type
Description

assetOwner

address

The address of the token owner/holder.

validateDepositAmount

Validates the deposit amount to ensure it is not 0 or more than the receiver can get. Calls the helper function _validateDepositAmount to check the deposit amount and receiver.

modifier validateDepositAmount(uint256 assets, address receiver);

Parameters

Name
Type
Description

assets

uint256

The amount of token to deposit.

receiver

address

The address receiving the deposit.

insufficientUnderlying

Validates if the underlying locked is always >= than the total supply of riskON/OFF reverts if not

modifier insufficientUnderlying();

depositLimitHit

Validates if the user has hit the periodic deposit limit prevents the user from depositing more if hit

modifier depositLimitHit(uint256 amount);

Parameters

Name
Type
Description

amount

uint256

The amount of token to deposit.

withdrawLimitHit

Validates if the user has hit the periodic withdraw limit prevents the user from withdrawing more if hit

modifier withdrawLimitHit(uint256 amount);

Parameters

Name
Type
Description

amount

uint256

The amount of token to withdraw.

dailyFFUpdate

modifier dailyFFUpdate();

expiryDateCheck

modifier expiryDateCheck(uint256 expiryDate);

constructor

constructor();

initialize

Initializes(replacement for the constructor) the SmartToken contract with specified parameters.

This function sets up the initial state of the SmartToken contract. Callable only once. It initializes inherited contracts and sets the initial values for tokenFactory and underlyingToken.

function initialize(
    string memory tokenName,
    string memory tokenSymbol,
    address factoryAddress,
    address sanctionsContract_,
    bool isX_,
    address owner_
) public initializer;

Parameters

Name
Type
Description

tokenName

string

The name of the token.

tokenSymbol

string

The symbol of the token.

factoryAddress

address

The address of the TokenFactory contract.

sanctionsContract_

address

The address of the SanctionsList contract.

isX_

bool

owner_

address

receive

receive() external payable;

drain

method to drain contracts of any ethers

This function can only be called by the contract owner.

function drain(address receiver) external onlyOwner;

Parameters

Name
Type
Description

receiver

address

The address of the account that will receive the ethers.

_authorizeUpgrade

Authorizes an upgrade to a new contract implementation.

This function can only be called by the contract owner. It overrides the _authorizeUpgrade function from the UUPSUpgradeable contract to include the onlyOwner modifier, ensuring only the owner can authorize upgrades.

function _authorizeUpgrade(address) internal override onlyOwner;

mintAsset

Mints the specified amount of tokens to the receiver.

This function can only be called by the TokenFactory contract.

function mintAsset(address receiver, uint256 amount) external onlyTokenFactory;

Parameters

Name
Type
Description

receiver

address

The address of the account that will receive the minted tokens.

amount

uint256

The amount of tokens to mint.

burn

Burns the specified amount of tokens from the account.

This function can only be called by the TokenFactory contract.

function burn(address account, uint256 amount) external onlyTokenFactory;

Parameters

Name
Type
Description

account

address

The address of the account from which tokens will be burned.

amount

uint256

The amount of tokens to burn.

transfer

Transfers the specified amount of tokens to the specified recipient.

Overrides the transfer function from ERC20Upgradeable and IERC20Upgradeable contracts. If the sender or receiver has a pending rebalance, it is handled before the transfer. This function can only be called when transfers are not stopped, and neither the sender nor the recipient are on the sanctions list.

function transfer(address recipient, uint256 amount)
    public
    override(ERC20Upgradeable, IERC20Upgradeable)
    stopTransfer
    insufficientUnderlying
    onlyNotSanctioned(recipient)
    onlyNotSanctioned(_msgSender())
    dailyFFUpdate
    returns (bool);

Parameters

Name
Type
Description

recipient

address

The address to which tokens will be transferred.

amount

uint256

The amount of tokens to transfer.

Returns

Name
Type
Description

<none>

bool

Always return true unless reverted

smartTreasuryTransfer

function smartTreasuryTransfer(address treasuryAddress, uint256 amount) external onlyTokenFactory;

smartBalanceAdjust

function smartBalanceAdjust(address account, uint256 amount) external onlyTokenFactory;

balanceOf

Returns the balance of the specified account

Overrides the balanceOf function from the inherited ERC20Upgradeable and IERC20Upgradeable contracts. If the account has a pending rebalance, the function calculates the calculated balance post rebalance using the 'calculateRollOverValue' method. Otherwise, it returns the erc20 balance using unScaledbalanceOf method.

function balanceOf(address account) public view override(ERC20Upgradeable, IERC20Upgradeable) returns (uint256);

Parameters

Name
Type
Description

account

address

The address of the account whose balance will be retrieved.

Returns

Name
Type
Description

<none>

uint256

The balance of the specified account.

unScaledbalanceOf

Returns the unscaled(unaffected by pending rebalances) balance of the specified account.

This function returns the ERC20 balance(unaffected by pending rebalances) of the account.

function unScaledbalanceOf(address account) public view returns (uint256);

Parameters

Name
Type
Description

account

address

The address of the account.

Returns

Name
Type
Description

<none>

uint256

The unscaled(unaffected by pending rebalances) balance of the specified account.

hasPendingRebalance

Checks if the specified account has a pending rebalance.

Compares the account's last rebalance count with the current scalingfactor length to determine if a rebalance is pending.

function hasPendingRebalance(address account) public view returns (bool);

Parameters

Name
Type
Description

account

address

The address of the account

Returns

Name
Type
Description

<none>

bool

A boolean value indicating whether the specified account has a pending rebalance.

getTokenFactory

Retrieves the address of the Vault (TokenFactory) contract.

This function casts the tokenFactory variable to an address and returns it.

function getTokenFactory() public view returns (address);

Returns

Name
Type
Description

<none>

address

The address of the Vault (TokenFactory) contract.

transferFrom

Transfers the specified amount of tokens from the sender to the recipient.

Overrides the transferFrom function from the inherited ERC20Upgradeable and IERC20Upgradeable contracts. If the sender or recipient has a pending rebalance, it is handled before the transfer. This function can only be called when transfers are not stopped, and neither the sender nor the recipient are on the sanctions list.

function transferFrom(address sender, address recipient, uint256 amount)
    public
    override(ERC20Upgradeable, IERC20Upgradeable)
    stopTransfer
    insufficientUnderlying
    dailyFFUpdate
    onlyNotSanctioned(recipient)
    onlyNotSanctioned(sender)
    returns (bool);

Parameters

Name
Type
Description

sender

address

The address from which tokens will be transferred.

recipient

address

The address to which tokens will be transferred.

amount

uint256

The amount of tokens to transfer.

Returns

Name
Type
Description

<none>

bool

A boolean value indicating whether the operation succeeded.

handlePendingRebalance

Handles pending rebalances for the sender and receiver addresses.

This function checks if the sender or receiver has a pending rebalance and applies the rebalance if needed.

function handlePendingRebalance(address sender, address receiver) public;

Parameters

Name
Type
Description

sender

address

The address of the sender involved in a transfer operation.

receiver

address

The address of the receiver involved in a transfer operation.

asset

Retrieves the address of the underlying token.

It overrides the asset function from the IERC4626Upgradeable interface.

function asset() public view virtual override returns (address);

Returns

Name
Type
Description

<none>

address

The address of the underlying token.

totalAssets

Retrieves the total amount of assets held by the TokenFactory.

It overrides the totalAssets function from the IERC4626Upgradeable interface.

function totalAssets() public view virtual override returns (uint256);

Returns

Name
Type
Description

<none>

uint256

The total amount of assets held by the Vault(TokenFactory).

convertToShares

Converts a specified amount of underlying assets to shares(RiskOn/Off).

It overrides the convertToShares function from the IERC4626Upgradeable interface.

function convertToShares(uint256 assets) public view virtual override returns (uint256 shares);

Parameters

Name
Type
Description

assets

uint256

The amount of assets to convert to shares.

Returns

Name
Type
Description

shares

uint256

The amount of shares(RiskOn/Off) for the amount of assets.

convertToAssets

Converts a specified amount of shares(RiskOn/Off) to underlying assets.

It overrides the convertToAssets function from the IERC4626Upgradeable interface.

function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets);

Parameters

Name
Type
Description

shares

uint256

The amount of shares to convert to assets.

Returns

Name
Type
Description

assets

uint256

The amount of assets for the amount of shares(RiskOn/Off).

maxDeposit

Calculates the maximum amount of assets that can be deposited by a specific account.

It overrides the maxDeposit function from the IERC4626Upgradeable interface.

function maxDeposit(address account) public view virtual override returns (uint256);

Parameters

Name
Type
Description

account

address

The address of the account for which to calculate the maximum deposit amount.

Returns

Name
Type
Description

<none>

uint256

The maximum amount of assets that can be deposited by the account.

previewDeposit

Provides a preview of the number of shares(RiskOn/Off) that would be received for a amount of assets.

It overrides the previewDeposit function from the IERC4626Upgradeable interface.

function previewDeposit(uint256 assets) public view virtual override returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of assets to preview the deposit.

Returns

Name
Type
Description

<none>

uint256

The amount of shares(RiskOn/Off) for the specified amount of assets.

deposit

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver.

It overrides the deposit function from the IERC4626Upgradeable interface. The stopDeposit circuit breaker can be used to freeze deposits and validateDepositAmount modifier to validate the deposit amount

function deposit(uint256 assets, address receiver)
    public
    virtual
    override
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of assets to deposit.

receiver

address

The receiver address.

Returns

Name
Type
Description

<none>

uint256

The amount of shares(RiskOn/Off) the receiver will get.

depositWithPermit

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver with an EIP-2612 permit for approval.

It overrides the deposit function from the IERC4626Upgradeable interface. The stopDeposit circuit breaker can be used to freeze deposits and validateDepositAmount modifier to validate the deposit amount then calls permit on the underlyingToken to set the allowance,

function depositWithPermit(uint256 assets, address receiver, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
    public
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets to deposit.

receiver

address

The address of the receiver

deadline

uint256

The deadline for the permit signature to be valid, as a UNIX timestamp.

v

uint8

The recovery byte of the signature.

r

bytes32

part of the ECDSA signature pair.

s

bytes32

part of the ECDSA signature pair.

Returns

Name
Type
Description

<none>

uint256

The amount of shares(RiskOn/Off) the receiber will get

depositWithExpiry

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver.

It overrides the deposit function from the IERC4626Upgradeable interface. The stopDeposit circuit breaker can be used to freeze deposits and validateDepositAmount modifier to validate the deposit amount

function depositWithExpiry(uint256 assets, address receiver, uint256 expiryDate)
    public
    virtual
    expiryDateCheck(expiryDate)
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of assets to deposit.

receiver

address

The receiver address.

expiryDate

uint256

The expiry date for the deposit.

Returns

Name
Type
Description

<none>

uint256

The amount of shares(RiskOn/Off) the receiver will get.

depositWithNative

Deposits an amount of underlying (NATIVE) assets, crediting the shares(RiskON/OFF) to the receiver.

It uses msg.value as the deposit amount. The stopDeposit circuit breaker can be used to freeze deposits and validateDepositAmount modifier to validate the deposit amount

function depositWithNative(address receiver)
    public
    payable
    virtual
    nonReentrant
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(msg.value)
    validateDepositAmount(msg.value, receiver)
    returns (uint256);

Parameters

Name
Type
Description

receiver

address

The receiver address.

Returns

Name
Type
Description

<none>

uint256

The amount of shares(RiskOn/Off) the receiver will get.

maxMint

Calculates the maximum amount of shares(RiskOn/Off) that can be minted for a user.

It overrides the maxMint function from the IERC4626Upgradeable interface.

function maxMint(address account) public view virtual override returns (uint256);

Parameters

Name
Type
Description

account

address

The address of user for which to calculate the maximum mintable shares(RiskOn/Off).

Returns

Name
Type
Description

<none>

uint256

The maximum amount of shares(RiskOn/Off) that can be minted for the user.

previewMint

Provides a preview of the amount of underlying assets required to mint a number of shares(RiskOn/Off).

It overrides the previewMint function from the IERC4626Upgradeable interface.

function previewMint(uint256 shares) public view virtual override returns (uint256);

Parameters

Name
Type
Description

shares

uint256

The number of shares(RiskOn/Off) to mint.

Returns

Name
Type
Description

<none>

uint256

The amount of underlying assets required to mint the specified number of shares(RiskOn/Off).

mint

mints an amount of shares, crediting the shares(RiskON/OFF) to the receiver.

It overrides the deposit function from the IERC4626Upgradeable interface. The stopDeposit circuit breaker can be used to freeze minting. As opposed to deposit, minting is allowed even if the vault is in a state where the price of a share is zero. In this case, the shares will be minted without requiring any assets to be deposited.

function mint(uint256 shares, address receiver)
    public
    virtual
    override
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(shares)
    returns (uint256);

Parameters

Name
Type
Description

shares

uint256

The amount of shares(RiskON/OFF) to mint.

receiver

address

The receiver address.

Returns

Name
Type
Description

<none>

uint256

The amount of assets that were deposited to mint the specified number of shares(RiskON/OFF).

maxWithdraw

Calculates the maximum amount of underlying assets that can be withdrawn by a specified owner.

It overrides the maxWithdraw function from the IERC4626Upgradeable interface.

function maxWithdraw(address owner_) public view virtual override returns (uint256);

Parameters

Name
Type
Description

owner_

address

The address of the owner for which to calculate the maximum underlying withdrawable assets.

Returns

Name
Type
Description

<none>

uint256

The maximum amount of assets that can be withdrawn by the specified owner.

previewWithdraw

Provide a preview of number of shares(RiskOn/Off) required to withdraw an amount of underlying assets.

It overrides the previewWithdraw function from the IERC4626Upgradeable interface.

function previewWithdraw(uint256 assets) public view virtual override returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of assets to withdraw.

Returns

Name
Type
Description

<none>

uint256

The number of shares(RiskOn/Off) required to withdraw the specified amount of assets.

withdraw

Allows an owner to withdraw a specified amount of underlying assets, transferring them to a receiver.

This function overrides the withdraw function from the IERC4626Upgradeable interface, and is guarded by the stopWithdraw, onlyAssetOwner, and nonReentrant modifiers.

function withdraw(uint256 assets, address receiver, address owner_)
    public
    virtual
    override
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(assets)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets to withdraw.

receiver

address

The address to which the assets should be transferred.

owner_

address

The address of the owner making the withdrawal.

Returns

Name
Type
Description

<none>

uint256

The number of shares(RiskON/OFF) corresponding to the withdrawn assets.

withdrawWithExpiry

Allows an owner to withdraw a specified amount of underlying assets, transferring them to a receiver.

This function overrides the withdraw function from the IERC4626Upgradeable interface, and is guarded by the stopWithdraw, onlyAssetOwner, and nonReentrant modifiers.

function withdrawWithExpiry(uint256 assets, address receiver, address owner_, uint256 expiryDate)
    public
    virtual
    expiryDateCheck(expiryDate)
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(assets)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets to withdraw.

receiver

address

The address to which the assets should be transferred.

owner_

address

The address of the owner making the withdrawal.

expiryDate

uint256

The expiry date for the withdrawal.

Returns

Name
Type
Description

<none>

uint256

The number of shares(RiskON/OFF) corresponding to the withdrawn assets.

flashLoan

Allows user to take flashloans from the tokenFactory (Vault/POOL)

This function is guarded by the nonReentrant and stopFlashLoan modifiers. It makes use of AAVE's flashloan interface to provide backwards compatibility for ease of use

function flashLoan(address receiver, uint256 amount, bytes memory params)
    external
    nonReentrant
    stopFlashLoan
    onlyNotSanctioned(receiver)
    onlyNotSanctioned(_msgSender());

Parameters

Name
Type
Description

receiver

address

The address of the receiver.

amount

uint256

The amount of underlying assets to flashloan.

params

bytes

The parameters for the flashloan. Used by the receiver contract(Aave's interface)

maxRedeem

Computes the maximum amount of underlying assets that can be redeemed by owner.

It overrides the maxRedeem function from the IERC4626Upgradeable interface.

function maxRedeem(address owner_) public view virtual override returns (uint256);

Parameters

Name
Type
Description

owner_

address

The address of the owner.

Returns

Name
Type
Description

<none>

uint256

The maximum amount of underlying assets that the owner can redeem.

previewRedeem

Provides a preview of the amount of underlying assets that would be received when redeeming a number of shares(RiskON/OFF).

It overrides the previewRedeem function from the IERC4626Upgradeable interface.

function previewRedeem(uint256 shares) public view virtual override returns (uint256);

Parameters

Name
Type
Description

shares

uint256

The number of shares(RiskON/OFF) to compute the equivalent underlying asset amount for.

Returns

Name
Type
Description

<none>

uint256

The equivalent asset amount for the given number of shares(RiskON/OFF).

redeem

Allows a user to redeem some amount of underlying assets based on an input amount of shares(RiskON/OFF).

See IERC4626-redeem.

It overrides the redeem function from the IERC4626Upgradeable interface. and is guarded by the stopWithdraw, onlyAssetOwner, and nonReentrant modifiers.

function redeem(uint256 shares, address receiver, address owner_)
    public
    virtual
    override
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(shares)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);

Parameters

Name
Type
Description

shares

uint256

The number of shares(RiskON/OFF) to redeem for underlying assets.

receiver

address

The address of receiver.

owner_

address

The address of the owner.

Returns

Name
Type
Description

<none>

uint256

The amount of underlying assets redeemed.

_onlyTokenFactory

Helpers for modifiers to reduce size

Checks if the caller is the Vault (tokenFactory)

This function is utilized by the onlyTokenFactory modifier to ensure that only the token factory can call certain functions.

function _onlyTokenFactory() private view;

_onlyAssetOwner

Checks if the caller is the asset owner.

This function is utilized by the onlyAssetOwner modifier to ensure that only the asset owner can call certain functions.

function _onlyAssetOwner(address assetOwner) private view;

Parameters

Name
Type
Description

assetOwner

address

The address of the asset owner.

_validateDepositAmount

Validates the deposit amount.

This function is utilized by the validateDepositAmount modifier to ensure that the deposit amount is neither zero nor exceeds the maximum allowed deposit for the receiver.

function _validateDepositAmount(uint256 assets, address receiver) private view;

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets being deposited.

receiver

address

The address of the receiver

hasPendingFF

function hasPendingFF(address account) public view returns (bool);

handlePendingFF

function handlePendingFF(address sender, address receiver) public;

_handleDeposit

function _handleDeposit(uint256 assets, address receiver) private returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets to deposit.@note WE can use SHARES as well since it's a 1:1 conversion

receiver

address

The address to which the assets should be transferred.

_handleWithdraw

function _handleWithdraw(uint256 assets, address receiver, address owner_) private returns (uint256);

Parameters

Name
Type
Description

assets

uint256

The amount of underlying assets to withdraw. @note WE can use SHARES as well since it's a 1:1 conversion

receiver

address

The address to which the assets should be transferred.

owner_

address

The address of the owner making the withdrawal.

getFlashLoanPool

Retrieves the address of the flashloan POOL (TokenFactory) contract.

This function casts the tokenFactory variable to an address and returns it.

function getFlashLoanPool() public view returns (address);

Returns

Name
Type
Description

<none>

address

The address of the flashloan POOL (TokenFactory) contract.

Errors

SmartToken__NotTokenFactory

error SmartToken__NotTokenFactory();

SmartToken__MethodNotAllowed

error SmartToken__MethodNotAllowed();

SmartToken__DepositMoreThanMax

error SmartToken__DepositMoreThanMax();

SmartToken__MintMoreThanMax

error SmartToken__MintMoreThanMax();

SmartToken__WithdrawMoreThanMax

error SmartToken__WithdrawMoreThanMax();

SmartToken__RedeemMoreThanMax

error SmartToken__RedeemMoreThanMax();

SmartToken__OnlyAssetOwner

error SmartToken__OnlyAssetOwner();

SmartToken__ZeroDeposit

error SmartToken__ZeroDeposit();

SmartToken__InsufficientUnderlying

error SmartToken__InsufficientUnderlying();

SmartToken__DepositLimitHit

error SmartToken__DepositLimitHit();

SmartToken__WithdrawLimitHit

error SmartToken__WithdrawLimitHit();

SmartToken__ExpiryDateReached

error SmartToken__ExpiryDateReached();

SmartToken__WithdrawNativeFailed

error SmartToken__WithdrawNativeFailed();

Last updated