UNPKG

@gnosis.pm/dex-contracts

Version:

Contracts for dFusion multi-token batch auction exchange

84 lines (83 loc) 4.58 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWithdrawableAmount = exports.getBalanceState = void 0; const bn_js_1 = __importDefault(require("bn.js")); const WORD_DATA_LENGTH = 64; /** * Retrieves user's token balance as stored in the "balance" entry of the private exchange mapping balanceStates * Value is directly read from storage relying on Solidity's layout of storage variables * See https://solidity.readthedocs.io/en/develop/internals/layout_in_storage.html * @param userAddress - address of the user * @param tokenAddress - address of the token * @param batchExchangeAddress - address of the batch exchange * @param web3Provider - provider of Ethereum JavaScript API * @returns balance of the token for the given user as stored in balanceStates[userAddress][tokenAddress].balance */ function getBalanceState(userAddress, tokenAddress, batchExchangeAddress, web3Provider = web3) { return __awaiter(this, void 0, void 0, function* () { // TODO when Truffle depends on web3-utils version ^1.2.5: // use soliditySha3Raw instead of soliditySha3 and remove type coercion const BALANCESTATES_STORAGE_SLOT = "0x0"; const userBalancestatesStorageSlot = web3Provider.utils.soliditySha3({ type: "bytes32", value: web3Provider.utils.padLeft(userAddress, WORD_DATA_LENGTH), }, { type: "bytes32", value: web3Provider.utils.padLeft(BALANCESTATES_STORAGE_SLOT, WORD_DATA_LENGTH), }); const targetStorageSlot = web3Provider.utils.soliditySha3({ type: "bytes32", value: web3Provider.utils.padLeft(tokenAddress, WORD_DATA_LENGTH), }, { type: "bytes32", value: web3Provider.utils.padLeft(userBalancestatesStorageSlot, WORD_DATA_LENGTH), }); const storageAtSlot = yield web3Provider.eth.getStorageAt(batchExchangeAddress, targetStorageSlot); return web3Provider.utils.toBN(storageAtSlot); }); } exports.getBalanceState = getBalanceState; /** * Computes amount of a token that a user can immediately withdraw from the exchange * It not only checks whether a withdrawal is pending, but also considers the balance available to the user, * pending deposits, and whether there were recent trades that would make withdrawing fail. * @param userAddress - address of the user * @param tokenAddress - address of the token * @param batchExchange - object representing the batch exchange smart contract * @param web3Provider - provider of Ethereum JavaScript API * @returns amount of token that the user would receive by calling batchExchange.withdraw */ function getWithdrawableAmount(userAddress, tokenAddress, batchExchange, web3Provider = web3) { return __awaiter(this, void 0, void 0, function* () { const [balanceState, pendingDeposit, pendingWithdrawal, lastCreditBatchId, batchId,] = yield Promise.all([ getBalanceState(userAddress, tokenAddress, batchExchange.address, web3Provider), batchExchange.getPendingDeposit(userAddress, tokenAddress), batchExchange.getPendingWithdraw(userAddress, tokenAddress), batchExchange.lastCreditBatchId(userAddress, tokenAddress), batchExchange.getCurrentBatchId(), ]); let balance = balanceState; if (pendingDeposit[1].lt(batchId)) { balance = balance.add(pendingDeposit[0]); } if (pendingWithdrawal[1].gte(batchId) || lastCreditBatchId.gte(batchId)) { return new bn_js_1.default(0); } else { return bn_js_1.default.min(balance, pendingWithdrawal[0]); } }); } exports.getWithdrawableAmount = getWithdrawableAmount;