Skip to main content

Deposit and Withdraw

Background Knowledge

  • What is ERC20

    ERC-20 is the technical standard for creating fungible tokens on the Ethereum blockchain. It defines a standard set of rules that must be followed for a token to function correctly within the Ethereum ecosystem. Please refer to the official guidance at https://docs.openzeppelin.com/contracts/4.x/erc20 for further information.

  • ERC20 decimal

    Decimals indicate the divisibility of a token, ranging from 0 (non-divisible) to 18 (highly divisible) or even higher if needed.

  • Approve

    Approve is an ERC20 token contract function. It grants permission for a spender (such as an exchange or EOA) to withdraw up to a specified value multiple times from your token contract.

Primary Asset & Secondary Asset

  • The primary asset is the system settlement token used for settling all PNL. It may vary across different chains, but commonly used stablecoins often serve as primary assets. Users can trade on the JOJO Exchange by depositing primary assets as margin. Call IDealer#primaryAsset() to find the primary asset address.

  • Secondary asset is designed to solve the liquidity issue of primary assets. It is utilized for trading margin and the multi-collateral system (to be introduced in V1.1). Within the JOJO Exchange, secondary assets are considered equal in value to primary assets. Call IDealer#secondaryAsset() to find the secondary asset address.

  • JUSD is a stablecoin that has been issued by JOJO as a secondary asset. It operates in a manner similar to DAI, which means that users can mint JUSD by staking other ERC20 tokens as collateral. While JUSD can be traded freely, it's important to note that its price is not guaranteed to match the primary asset in the open market.

Deposit

Smart Contract Function

Users deposit primary or secondary assets as margin for trading by calling IDealer#deposit.

/// @notice deposit function: user deposit their collateral.
/// @param from: deposit from which account
/// @param collateral: deposit collateral type.
/// @param amount: collateral amount
/// @param to: account that user want to deposit to
function deposit(address from, address collateral, uint256 amount, address to) external;

Withdraw

Withdrawal Pending Period Mode

  • To withdraw funds, you need to follow two steps: first, submit a request for withdrawal, and second, execute the withdrawal. Note that the time between these two steps must exceed the timelock. This is designed to increase the success rate of settlements by reducing the user's available balance immediately upon receiving the withdrawal request. This step prevents any invalid matches from happening.

  • The timelock value, in seconds, can be found by calling IDealer#withdrawTimeLock. After submitting a withdrawal request, users can find the executable timestamp by calling IDealer#withdrawExecutionTimestamp. Pending withdrawal amounts can be found by calling IDealer#pendingSecondaryWithdraw and IDealer#pendingPrimaryWithdraw.

/// @notice Submit withdrawal request, which can be executed after
/// the timelock. The main purpose of this function is to avoid the
/// failure of counterparty caused by withdrawal.
/// @param from The deducted account.
/// @param primaryAmount is the amount of primary asset you want to withdraw.
/// @param secondaryAmount is the amount of secondary asset you want to withdraw.
function requestWithdraw(
address from,
uint256 primaryAmount,
uint256 secondaryAmount
) external;

/// @notice Execute the withdrawal request.
/// @param from The deducted account.
/// @param to is the address receiving assets.
/// @param isInternal Only internal credit transfers will be made,
/// and ERC20 transfers will not happen.
/// @param param call "to" with param if not null.
function executeWithdraw(
address from,
address to,
bool isInternal,
bytes memory param
) external;

Fast Withdrawal Mode

  • In Fast Withdraw mode, the fastWithdrawDisabled is turned off. This allows for quick withdrawals without any waiting period when users wish to withdraw funds.
/// @notice Withdraw without waiting.
/// @param from The deducted account.
/// @param to is the address receiving assets.
/// @param primaryAmount is the amount of primary asset you want to withdraw.
/// @param secondaryAmount is the amount of secondary asset you want to
/// @param isInternal Only internal credit transfers will be made,
/// and ERC20 transfers will not happen.
/// @param param call "to" with param if not null.
function fastWithdraw(
address from,
address to,
uint256 primaryAmount,
uint256 secondaryAmount,
bool isInternal,
bytes memory param
) external;

Safe Check

  • Prior to withdrawal, the system assesses the safety of the account's positions by checking:

    netPositionValue+primaryCredit+secondaryCreditinitialMarginnetPositionValue +primaryCredit + secondaryCredit \geq initialMargin
  • If a trader attempts to withdraw any amount of the primary asset, an additional check is performed:

netPositionValue+primaryCredit0netPositionValue + primaryCredit \geq 0
  • This check prevents users from depositing secondary assets and withdrawing primary assets, which would infringe on the liquidity of primary assets and violate the multi-collateral protocol's intent.

  • Only internal credit changes occur for internal transfers, and no ERC20 transfers occur.