@gnosis.pm/dex-contracts
Version:
Contracts for dFusion multi-token batch auction exchange
84 lines (83 loc) • 4.58 kB
JavaScript
;
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;