Mitigating Risks: Custody of funds – DMEX
In DMEX all user funds are stored on the custody smart contract.
Note: We require that funds are deposited to the contract before trading because otherwise we cannot lock the margin and the trader would be able to withdraw funds from his/her wallet when incurring a loss on a position and avoid paying the margin.
The structure of the custody contract
All funds entering the contract are assigned to the wallet address from which the funds were sent. All funds on the contract are assigned to wallet addresses. There are no unassigned funds in the contract. The total of the funds assigned to the wallets equals to the total funds in the contract.
Withdrawal of funds
In order to withdraw funds from the contract a wallet needs to be provided and the signature from the wallet authorizing the withdrawal. Withdrawal is only possible to the wallet that deposited the funds. User can withdraw the funds by calling the withdraw() function on the contract or using the web interface to request a withdrawal through our servers.
For the second method, the user generates a signature with the amount and gas fee which is sent to the server with the withdrawal request. The backend server then calls the adminWithdraw() function on the contract providing the signature from the user.
Note: The adminWIthdraw() function is implemented in the contract to make the user experience easier. When using the withdraw() function directly the user might experience difficulties in tracking the transaction and handling potential errors. When requesting the withdrawal from the website, the request is first validated against the user balance and an error is given straight away.
Balance manipulations
Changes to user balances can be performed only by the trading smart contract. The trading smart contract is defined in the custody contract in the futuresContracts mapping. Only one futures contract can be added, so we cannot add a different trading contract later and empty user accounts.
Trading Contract
For safety purposes, the user should be interested in the following functions that can reduce the balance or increase the reserve (the reserve is the amount of funds locked in the user’s account while a position is opened and cannot be withdrawn):
- addBalance() — used to increase user balance
1. Invoked by the updateBalances() function (called by futuresTrade()). Used to add the trading fee to the feeAccount.
2. Invoked by closeFuturesPositionInternal() used to add the profit to the user in case of a profit from the trade to the user or the pool depending on the settlement price and the funding cost to the feeAccount . This function uses the closing price provided by the oracle to settle positions.
3. Invoked by the liquidatePosition() function called when the position reaches the liquidation price. Adds the liquidated position’s margin to the pool account. This function uses the price provided by the oracle to determine if the liquidation price is reached. - subBalance() — used to reduce the user balance
Is invoked in the closeFuturesPositionInternal() function. This method closes a position when the futures contract expires using the settlement price provided by the oracle. It calculates the profit/loss based on the closing price and either increases the user balance or reduces it. - addBalanceSubReserve() — used to increase the user balance and remove the reserve
Invoked by the updateBalances() function when a user closes/partially closes his/her position and makes a profit. Used to add the profit and remove the reserve from the user account. - subBalanceAddReserve() — used to reduce the user balance and reserve funds at the same time.
Invoked only in the updateBalances() function which is called by the futuresTrade() method. Is used to deduct the trading fee from the user balance and reserve the margin. - subBalanceSubReserve() — used to reduce the user balance and remove reserve at the same time
1. Invoked in the updateBalances() function used by the futuresTrade() function. The function is used to reduce the balance and reserves when the user decreases his/her position and makes a loss.
2. Invoked in liquidatePosition() function used to liquidate a position when the liquidation price is reached. The liquidation is performed based on the price received from the oracle.
All functions inside the trading contract that can manipulate user balances have a specific purpose and were developed with user safety in mind. All functions have a specific point of entry and perform validations to make sure the operation is intended by the user.
Published at Sat, 28 Sep 2019 07:33:22 +0000
{flickr|100|campaign}
