forked from mobiusAMM/mobiusV1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
swapdata.json
1 lines (1 loc) · 117 KB
/
swapdata.json
1
{"flattened_source": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\n\n\n// Part: Address\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n\n// Part: Context\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n\n// Part: IERC20\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n\n// Part: MathUtils\n\n/**\n * @title MathUtils library\n * @notice A library to be used in conjunction with SafeMath. Contains functions for calculating\n * differences between two uint256.\n */\nlibrary MathUtils {\n /**\n * @notice Compares a and b and returns true if the difference between a and b\n * is less than 1 or equal to each other.\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return True if the difference between a and b is less than 1 or equal,\n * otherwise return false\n */\n function within1(uint256 a, uint256 b) external pure returns (bool) {\n return (_difference(a, b) <= 1);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function difference(uint256 a, uint256 b) external pure returns (uint256) {\n return _difference(a, b);\n }\n\n /**\n * @notice Calculates absolute difference between a and b\n * @param a uint256 to compare with\n * @param b uint256 to compare with\n * @return Difference between a and b\n */\n function _difference(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a > b) {\n return a - b;\n }\n return b - a;\n }\n}\n\n// Part: ReentrancyGuard\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor () internal {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n\n// Part: SafeMath\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n\n// Part: ERC20\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n\n// Part: ISwap\n\ninterface ISwap {\n // pool data view functions\n function getA() external view returns (uint256);\n\n function getToken(uint8 index) external view returns (IERC20);\n\n function getTokenIndex(address tokenAddress) external view returns (uint8);\n\n function getTokenBalance(uint8 index) external view returns (uint256);\n\n function getVirtualPrice() external view returns (uint256);\n\n // min return calculation functions\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256);\n\n function calculateTokenAmount(\n address account,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256);\n\n function calculateRemoveLiquidity(address account, uint256 amount)\n external\n view\n returns (uint256[] memory);\n\n function calculateRemoveLiquidityOneToken(\n address account,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount);\n\n // state modifying functions\n function initialize(\n IERC20[] memory pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 a,\n uint256 fee,\n uint256 adminFee,\n uint256 depositFee,\n uint256 withdrawFee,\n address devaddr\n ) external;\n\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external returns (uint256[] memory);\n\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n ) external returns (uint256);\n\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n ) external returns (uint256);\n\n // withdraw fee update function\n function updateUserWithdrawFee(address recipient, uint256 transferAmount)\n external;\n}\n\n// Part: Ownable\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n\n// Part: Pausable\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor () internal {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n\n// Part: SafeERC20\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n\n// Part: ERC20Burnable\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n using SafeMath for uint256;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\n\n _approve(account, _msgSender(), decreasedAllowance);\n _burn(account, amount);\n }\n}\n\n// Part: OwnerPausable\n\n/**\n * @title OwnerPausable\n * @notice An ownable contract allows the owner to pause and unpause the\n * contract without a delay.\n * @dev Only methods using the provided modifiers will be paused.\n */\ncontract OwnerPausable is Ownable, Pausable {\n /**\n * @notice Pause the contract. Revert if already paused.\n */\n function pause() external onlyOwner {\n Pausable._pause();\n }\n\n /**\n * @notice Unpause the contract. Revert if already unpaused.\n */\n function unpause() external onlyOwner {\n Pausable._unpause();\n }\n}\n\n// Part: LPToken\n\n/**\n * @title Liquidity Provider Token\n * @notice This token is an ERC20 detailed token with added capability to be minted by the owner.\n * It is used to represent user's shares when providing liquidity to swap contracts.\n */\ncontract LPToken is ERC20Burnable, Ownable {\n using SafeMath for uint256;\n\n // Address of the swap contract that owns this LP token. When a user adds liquidity to the swap contract,\n // they receive a proportionate amount of this LPToken.\n ISwap public immutable swap;\n\n /**\n * @notice Deploys LPToken contract with given name, symbol, and decimals\n * @dev the caller of this constructor will become the owner of this contract\n * @param name_ name of this token\n * @param symbol_ symbol of this token\n * @param decimals_ number of decimals this token will be based on\n */\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public ERC20(name_, symbol_) {\n _setupDecimals(decimals_);\n swap = ISwap(_msgSender());\n }\n\n /**\n * @notice Mints the given amount of LPToken to the recipient.\n * @dev only owner can call this mint function\n * @param recipient address of account to receive the tokens\n * @param amount amount of tokens to mint\n */\n function mint(\n address recipient,\n uint256 amount\n ) external onlyOwner {\n require(amount != 0, \"amount == 0\");\n _mint(recipient, amount);\n }\n\n /**\n * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including\n * minting and burning. This ensures that swap.updateUserWithdrawFees are called everytime.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20) {\n super._beforeTokenTransfer(from, to, amount);\n swap.updateUserWithdrawFee(to, amount);\n }\n}\n\n// Part: SwapUtils\n\n/**\n * @title SwapUtils library\n * @notice A library to be used within Swap.sol. Contains functions responsible for custody and AMM functionalities.\n * @dev Contracts relying on this library must initialize SwapUtils.Swap struct then use this library\n * for SwapUtils.Swap struct. Note that this library contains both functions called by users and admins.\n * Admin functions should be protected within contracts using this library.\n */\nlibrary SwapUtils {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n\n /*** EVENTS ***/\n\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event NewWithdrawFee(uint256 newWithdrawFee);\n event NewDepositFee(uint256 newDepositFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n struct Swap {\n // variables around the ramp management of A,\n // the amplification coefficient * n * (n - 1)\n // see https://www.curve.fi/stableswap-paper.pdf for details\n uint256 initialA;\n uint256 futureA;\n uint256 initialATime;\n uint256 futureATime;\n // fee calculation\n uint256 swapFee;\n uint256 adminFee;\n uint256 defaultDepositFee;\n uint256 defaultWithdrawFee;\n address devaddr;\n LPToken lpToken;\n // contract references for all tokens being pooled\n IERC20[] pooledTokens;\n // multipliers for each pooled token's precision to get to POOL_PRECISION_DECIMALS\n // for example, TBTC has 18 decimals, so the multiplier should be 1. WBTC\n // has 8, so the multiplier should be 10 ** 18 / 10 ** 8 => 10 ** 10\n uint256[] tokenPrecisionMultipliers;\n // the pool balance of each token, in the token's precision\n // the contract's actual token balance might differ\n uint256[] balances;\n mapping(address => uint256) depositTimestamp;\n mapping(address => uint256) withdrawFeeMultiplier;\n }\n\n // Struct storing variables used in calculations in the\n // calculateWithdrawOneTokenDY function to avoid stack too deep errors\n struct CalculateWithdrawOneTokenDYInfo {\n uint256 d0;\n uint256 d1;\n uint256 newY;\n uint256 feePerToken;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculation in addLiquidity function\n // to avoid stack too deep error\n struct AddLiquidityInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n }\n\n // Struct storing variables used in calculation in removeLiquidityImbalance function\n // to avoid stack too deep error\n struct RemoveLiquidityImbalanceInfo {\n uint256 d0;\n uint256 d1;\n uint256 d2;\n uint256 preciseA;\n }\n\n // the precision all pools tokens will be converted to\n uint8 public constant POOL_PRECISION_DECIMALS = 18;\n\n // the denominator used to calculate admin and LP fees. For example, an\n // LP fee might be something like tradeAmount.mul(fee).div(FEE_DENOMINATOR)\n uint256 private constant FEE_DENOMINATOR = 10**10;\n\n // Max swap fee is 1% or 100bps of each swap\n uint256 public constant MAX_SWAP_FEE = 10**8;\n\n // Max adminFee is 100% of the swapFee\n // adminFee does not add additional fee on top of swapFee\n // Instead it takes a certain % of the swapFee. Therefore it has no impact on the\n // users but only on the earnings of LPs\n uint256 public constant MAX_ADMIN_FEE = 10**10;\n\n // Max withdrawFee is 1% of the value withdrawn\n // Fee will be redistributed to the LPs in the pool, rewarding\n // long term providers.\n uint256 public constant MAX_WITHDRAW_FEE = 10**8;\n\n // Max depositFee is 1% of the value deposited\n uint256 public constant MAX_DEPOSIT_FEE = 10**8;\n \n // Constant value used as max loop limit\n uint256 private constant MAX_LOOP_LIMIT = 256;\n\n // Constant values used in ramping A calculations\n uint256 public constant A_PRECISION = 100;\n uint256 public constant MAX_A = 10**6;\n uint256 private constant MAX_A_CHANGE = 2;\n uint256 private constant MIN_RAMP_TIME = 14 days;\n\n /*** VIEW & PURE FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function getA(Swap storage self) external view returns (uint256) {\n return _getA(self);\n }\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter\n */\n function _getA(Swap storage self) internal view returns (uint256) {\n return _getAPrecise(self).div(A_PRECISION);\n }\n\n /**\n * @notice Return A in its raw precision\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function getAPrecise(Swap storage self) external view returns (uint256) {\n return _getAPrecise(self);\n }\n\n /**\n * @notice Calculates and returns A based on the ramp settings\n * @dev See the StableSwap paper for details\n * @param self Swap struct to read from\n * @return A parameter in its raw precision form\n */\n function _getAPrecise(Swap storage self) internal view returns (uint256) {\n uint256 t1 = self.futureATime; // time when ramp is finished\n uint256 a1 = self.futureA; // final A value when ramp is finished\n\n if (block.timestamp < t1) {\n uint256 t0 = self.initialATime; // time when ramp is started\n uint256 a0 = self.initialA; // initial A value when ramp is started\n if (a1 > a0) {\n // a0 + (a1 - a0) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.add(\n a1.sub(a0).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n } else {\n // a0 - (a0 - a1) * (block.timestamp - t0) / (t1 - t0)\n return\n a0.sub(\n a0.sub(a1).mul(block.timestamp.sub(t0)).div(t1.sub(t0))\n );\n }\n } else {\n return a1;\n }\n }\n\n /**\n * @notice Retrieves the timestamp of last deposit made by the given address\n * @param self Swap struct to read from\n * @return timestamp of last deposit\n */\n function getDepositTimestamp(Swap storage self, address user)\n external\n view\n returns (uint256)\n {\n return self.depositTimestamp[user];\n }\n\n /**\n * @notice Calculate the dy, the amount of selected token that user receives and\n * the fee of withdrawing in one token\n * @param account the address that is withdrawing\n * @param tokenAmount the amount to withdraw in the pool's precision\n * @param tokenIndex which token will be withdrawn\n * @param self Swap struct to read from\n * @return the amount of token user will receive and the associated swap fee\n */\n function calculateWithdrawOneToken(\n Swap storage self,\n address account,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) public view returns (uint256, uint256) {\n uint256 dy;\n uint256 newY;\n\n (dy, newY) = calculateWithdrawOneTokenDY(self, tokenIndex, tokenAmount);\n\n // dy_0 (without fees)\n // dy, dy_0 - dy\n\n uint256 dySwapFee =\n _xp(self)[tokenIndex]\n .sub(newY)\n .div(self.tokenPrecisionMultipliers[tokenIndex])\n .sub(dy);\n\n dy = dy\n .mul(\n FEE_DENOMINATOR.sub(calculateCurrentWithdrawFee(self, account))\n )\n .div(FEE_DENOMINATOR);\n\n return (dy, dySwapFee);\n }\n\n /**\n * @notice Calculate the dy of withdrawing in one token\n * @param self Swap struct to read from\n * @param tokenIndex which token will be withdrawn\n * @param tokenAmount the amount to withdraw in the pools precision\n * @return the d and the new y after withdrawing one token\n */\n function calculateWithdrawOneTokenDY(\n Swap storage self,\n uint8 tokenIndex,\n uint256 tokenAmount\n ) internal view returns (uint256, uint256) {\n require(\n tokenIndex < self.pooledTokens.length,\n \"Token index out of range\"\n );\n\n // Get the current D, then solve the stableswap invariant\n // y_i for D - tokenAmount\n uint256[] memory xp = _xp(self);\n CalculateWithdrawOneTokenDYInfo memory v =\n CalculateWithdrawOneTokenDYInfo(0, 0, 0, 0, 0);\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(xp, v.preciseA);\n v.d1 = v.d0.sub(tokenAmount.mul(v.d0).div(self.lpToken.totalSupply()));\n\n require(tokenAmount <= xp[tokenIndex], \"Withdraw exceeds available\");\n\n v.newY = getYD(v.preciseA, tokenIndex, xp, v.d1);\n\n uint256[] memory xpReduced = new uint256[](xp.length);\n\n v.feePerToken = _feePerToken(self);\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n uint256 xpi = xp[i];\n // if i == tokenIndex, dxExpected = xp[i] * d1 / d0 - newY\n // else dxExpected = xp[i] - (xp[i] * d1 / d0)\n // xpReduced[i] -= dxExpected * fee / FEE_DENOMINATOR\n xpReduced[i] = xpi.sub(\n (\n (i == tokenIndex)\n ? xpi.mul(v.d1).div(v.d0).sub(v.newY)\n : xpi.sub(xpi.mul(v.d1).div(v.d0))\n )\n .mul(v.feePerToken)\n .div(FEE_DENOMINATOR)\n );\n }\n\n uint256 dy =\n xpReduced[tokenIndex].sub(\n getYD(v.preciseA, tokenIndex, xpReduced, v.d1)\n );\n dy = dy.sub(1).div(self.tokenPrecisionMultipliers[tokenIndex]);\n\n return (dy, v.newY);\n }\n\n /**\n * @notice Calculate the price of a token in the pool with given\n * precision-adjusted balances and a particular D.\n *\n * @dev This is accomplished via solving the invariant iteratively.\n * See the StableSwap paper and Curve.fi implementation for further details.\n *\n * x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)\n * x_1**2 + b*x_1 = c\n * x_1 = (x_1**2 + c) / (2*x_1 + b)\n *\n * @param a the amplification coefficient * n * (n - 1). See the StableSwap paper for details.\n * @param tokenIndex Index of token we are calculating for.\n * @param xp a precision-adjusted set of pool balances. Array should be\n * the same cardinality as the pool.\n * @param d the stableswap invariant\n * @return the price of the token, in the same precision as in xp\n */\n function getYD(\n uint256 a,\n uint8 tokenIndex,\n uint256[] memory xp,\n uint256 d\n ) internal pure returns (uint256) {\n uint256 numTokens = xp.length;\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 c = d;\n uint256 s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < numTokens; i++) {\n if (i != tokenIndex) {\n s = s.add(xp[i]);\n c = c.mul(d).div(xp[i].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n }\n c = c.mul(d).mul(A_PRECISION).div(nA.mul(numTokens));\n\n uint256 b = s.add(d.mul(A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on a set of balances and a particular A.\n * @param xp a precision-adjusted set of pool balances. Array should be the same cardinality\n * as the pool.\n * @param a the amplification coefficient * n * (n - 1) in A_PRECISION.\n * See the StableSwap paper for details\n * @return the invariant, at the precision of the pool\n */\n function getD(uint256[] memory xp, uint256 a)\n internal\n pure\n returns (uint256)\n {\n uint256 numTokens = xp.length;\n uint256 s;\n for (uint256 i = 0; i < numTokens; i++) {\n s = s.add(xp[i]);\n }\n if (s == 0) {\n return 0;\n }\n\n uint256 prevD;\n uint256 d = s;\n uint256 nA = a.mul(numTokens);\n\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n uint256 dP = d;\n for (uint256 j = 0; j < numTokens; j++) {\n dP = dP.mul(d).div(xp[j].mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // dP = dP * D * D * D * ... overflow!\n }\n prevD = d;\n d = nA.mul(s).div(A_PRECISION).add(dP.mul(numTokens)).mul(d).div(\n nA.sub(A_PRECISION).mul(d).div(A_PRECISION).add(\n numTokens.add(1).mul(dP)\n )\n );\n if (d.within1(prevD)) {\n return d;\n }\n }\n\n // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong\n // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()`\n // function which does not rely on D.\n revert(\"D does not converge\");\n }\n\n /**\n * @notice Get D, the StableSwap invariant, based on self Swap struct\n * @param self Swap struct to read from\n * @return The invariant, at the precision of the pool\n */\n function getD(Swap storage self) internal view returns (uint256) {\n return getD(_xp(self), _getAPrecise(self));\n }\n\n /**\n * @notice Given a set of balances and precision multipliers, return the\n * precision-adjusted balances.\n *\n * @param balances an array of token balances, in their native precisions.\n * These should generally correspond with pooled tokens.\n *\n * @param precisionMultipliers an array of multipliers, corresponding to\n * the amounts in the balances array. When multiplied together they\n * should yield amounts at the pool's precision.\n *\n * @return an array of amounts \"scaled\" to the pool's precision\n */\n function _xp(\n uint256[] memory balances,\n uint256[] memory precisionMultipliers\n ) internal pure returns (uint256[] memory) {\n uint256 numTokens = balances.length;\n require(\n numTokens == precisionMultipliers.length,\n \"Balances must match multipliers\"\n );\n uint256[] memory xp = new uint256[](numTokens);\n for (uint256 i = 0; i < numTokens; i++) {\n xp[i] = balances[i].mul(precisionMultipliers[i]);\n }\n return xp;\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @param balances array of balances to scale\n * @return balances array \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self, uint256[] memory balances)\n internal\n view\n returns (uint256[] memory)\n {\n return _xp(balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Return the precision-adjusted balances of all tokens in the pool\n * @param self Swap struct to read from\n * @return the pool balances \"scaled\" to the pool's precision, allowing\n * them to be more easily compared.\n */\n function _xp(Swap storage self) internal view returns (uint256[] memory) {\n return _xp(self.balances, self.tokenPrecisionMultipliers);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @param self Swap struct to read from\n * @return the virtual price, scaled to precision of POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice(Swap storage self)\n external\n view\n returns (uint256)\n {\n uint256 d = getD(_xp(self), _getAPrecise(self));\n uint256 supply = self.lpToken.totalSupply();\n if (supply > 0) {\n return\n d.mul(10**uint256(ERC20(self.lpToken).decimals())).div(supply);\n }\n return 0;\n }\n\n /**\n * @notice Calculate the new balances of the tokens given the indexes of the token\n * that is swapped from (FROM) and the token that is swapped to (TO).\n * This function is used as a helper function to calculate how much TO token\n * the user should receive on swap.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom index of FROM token\n * @param tokenIndexTo index of TO token\n * @param x the new total amount of FROM token\n * @param xp balances of the tokens in the pool\n * @return the amount of TO token that should remain in the pool\n */\n function getY(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 x,\n uint256[] memory xp\n ) internal view returns (uint256) {\n uint256 numTokens = self.pooledTokens.length;\n require(\n tokenIndexFrom != tokenIndexTo,\n \"Can't compare token to itself\"\n );\n require(\n tokenIndexFrom < numTokens && tokenIndexTo < numTokens,\n \"Tokens must be in pool\"\n );\n\n uint256 a = _getAPrecise(self);\n uint256 d = getD(xp, a);\n uint256 c = d;\n uint256 s;\n uint256 nA = numTokens.mul(a);\n\n uint256 _x;\n for (uint256 i = 0; i < numTokens; i++) {\n if (i == tokenIndexFrom) {\n _x = x;\n } else if (i != tokenIndexTo) {\n _x = xp[i];\n } else {\n continue;\n }\n s = s.add(_x);\n c = c.mul(d).div(_x.mul(numTokens));\n // If we were to protect the division loss we would have to keep the denominator separate\n // and divide at the end. However this leads to overflow with large numTokens or/and D.\n // c = c * D * D * D * ... overflow!\n }\n c = c.mul(d).mul(A_PRECISION).div(nA.mul(numTokens));\n uint256 b = s.add(d.mul(A_PRECISION).div(nA));\n uint256 yPrev;\n uint256 y = d;\n\n // iterative approximation\n for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {\n yPrev = y;\n y = y.mul(y).add(c).div(y.mul(2).add(b).sub(d));\n if (y.within1(yPrev)) {\n return y;\n }\n }\n revert(\"Approximation did not converge\");\n }\n\n /**\n * @notice Externally calculates a swap between two tokens.\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n */\n function calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256 dy) {\n (dy, ) = _calculateSwap(self, tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice Internally calculates a swap between two tokens.\n *\n * @dev The caller is expected to transfer the actual amounts (dx and dy)\n * using the token contracts.\n *\n * @param self Swap struct to read from\n * @param tokenIndexFrom the token to sell\n * @param tokenIndexTo the token to buy\n * @param dx the number of tokens to sell. If the token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @return dy the number of tokens the user will get\n * @return dyFee the associated fee\n */\n function _calculateSwap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) internal view returns (uint256 dy, uint256 dyFee) {\n uint256[] memory xp = _xp(self);\n require(\n tokenIndexFrom < xp.length && tokenIndexTo < xp.length,\n \"Token index out of range\"\n );\n uint256 x =\n dx.mul(self.tokenPrecisionMultipliers[tokenIndexFrom]).add(\n xp[tokenIndexFrom]\n );\n uint256 y = getY(self, tokenIndexFrom, tokenIndexTo, x, xp);\n dy = xp[tokenIndexTo].sub(y).sub(1);\n dyFee = dy.mul(self.swapFee).div(FEE_DENOMINATOR);\n dy = dy.sub(dyFee).div(self.tokenPrecisionMultipliers[tokenIndexTo]);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of\n * LP tokens\n *\n * @param account the address that is removing liquidity. required for withdraw fee calculation\n * @param amount the amount of LP tokens that would to be burned on\n * withdrawal\n * @return array of amounts of tokens user will receive\n */\n function calculateRemoveLiquidity(\n Swap storage self,\n address account,\n uint256 amount\n ) external view returns (uint256[] memory) {\n return _calculateRemoveLiquidity(self, account, amount);\n }\n\n function _calculateRemoveLiquidity(\n Swap storage self,\n address account,\n uint256 amount\n ) internal view returns (uint256[] memory) {\n uint256 totalSupply = self.lpToken.totalSupply();\n require(amount <= totalSupply, \"Cannot exceed total supply\");\n\n uint256 feeAdjustedAmount = amount;\n\n // No fees for withdrawals!\n // amount\n // .mul(\n // FEE_DENOMINATOR.sub(calculateCurrentWithdrawFee(self, account))\n // )\n // .div(FEE_DENOMINATOR);\n\n uint256[] memory amounts = new uint256[](self.pooledTokens.length);\n\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n amounts[i] = self.balances[i].mul(feeAdjustedAmount).div(\n totalSupply\n );\n }\n return amounts;\n }\n\n /**\n * @notice Calculate the fee that is applied when the given user withdraws.\n * Withdraw fee decays linearly over 4 weeks.\n * @param user address you want to calculate withdraw fee of\n * @return current withdraw fee of the user\n */\n function calculateCurrentWithdrawFee(Swap storage self, address user)\n public\n view\n returns (uint256)\n {\n uint256 endTime = self.depositTimestamp[user].add(4 weeks);\n if (endTime > block.timestamp) {\n uint256 timeLeftover = endTime.sub(block.timestamp);\n return\n self\n .defaultWithdrawFee\n .mul(self.withdrawFeeMultiplier[user])\n .mul(timeLeftover)\n .div(4 weeks)\n .div(FEE_DENOMINATOR);\n }\n return 0;\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param self Swap struct to read from\n * @param account address of the account depositing or withdrawing tokens\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return if deposit was true, total amount of lp token that will be minted and if\n * deposit was false, total amount of lp token that will be burned\n */\n function calculateTokenAmount(\n Swap storage self,\n address account,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n uint256 numTokens = self.pooledTokens.length;\n uint256 a = _getAPrecise(self);\n uint256 d0 = getD(_xp(self, self.balances), a);\n uint256[] memory balances1 = self.balances;\n for (uint256 i = 0; i < numTokens; i++) {\n if (deposit) {\n balances1[i] = balances1[i].add(amounts[i]);\n } else {\n balances1[i] = balances1[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n }\n uint256 d1 = getD(_xp(self, balances1), a);\n uint256 totalSupply = self.lpToken.totalSupply();\n\n if (deposit) {\n return d1.sub(d0).mul(totalSupply).div(d0);\n } else {\n return\n d0.sub(d1).mul(totalSupply).div(d0).mul(FEE_DENOMINATOR).div(\n FEE_DENOMINATOR.sub(\n calculateCurrentWithdrawFee(self, account)\n )\n );\n }\n }\n\n /**\n * @notice return accumulated amount of admin fees of the token with given index\n * @param self Swap struct to read from\n * @param index Index of the pooled token\n * @return admin balance in the token's precision\n */\n function getAdminBalance(Swap storage self, uint256 index)\n external\n view\n returns (uint256)\n {\n require(index < self.pooledTokens.length, \"Token index out of range\");\n return\n self.pooledTokens[index].balanceOf(address(this)).sub(\n self.balances[index]\n );\n }\n\n /**\n * @notice internal helper function to calculate fee per token multiplier used in\n * swap fee calculations\n * @param self Swap struct to read from\n */\n function _feePerToken(Swap storage self) internal view returns (uint256) {\n return\n self.swapFee.mul(self.pooledTokens.length).div(\n self.pooledTokens.length.sub(1).mul(4)\n );\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice swap two tokens in the pool\n * @param self Swap struct to read from and write to\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell\n * @param minDy the min amount the user would like to receive, or revert.\n * @return amount of token user received on swap\n */\n function swap(\n Swap storage self,\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy\n ) external returns (uint256) {\n require(\n dx <= self.pooledTokens[tokenIndexFrom].balanceOf(msg.sender),\n \"Cannot swap more than you own\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n uint256 beforeBalance =\n self.pooledTokens[tokenIndexFrom].balanceOf(address(this));\n self.pooledTokens[tokenIndexFrom].safeTransferFrom(\n msg.sender,\n address(this),\n dx\n );\n\n // Use the actual transferred amount for AMM math\n uint256 transferredDx =\n self.pooledTokens[tokenIndexFrom].balanceOf(address(this)).sub(\n beforeBalance\n );\n\n (uint256 dy, uint256 dyFee) =\n _calculateSwap(self, tokenIndexFrom, tokenIndexTo, transferredDx);\n require(dy >= minDy, \"Swap didn't result in min tokens\");\n\n uint256 dyAdminFee =\n dyFee.mul(self.adminFee).div(FEE_DENOMINATOR).div(\n self.tokenPrecisionMultipliers[tokenIndexTo]\n );\n\n self.balances[tokenIndexFrom] = self.balances[tokenIndexFrom].add(\n transferredDx\n );\n self.balances[tokenIndexTo] = self.balances[tokenIndexTo].sub(dy).sub(\n dyAdminFee\n );\n\n self.pooledTokens[tokenIndexTo].safeTransfer(msg.sender, dy);\n\n emit TokenSwap(\n msg.sender,\n transferredDx,\n dy,\n tokenIndexFrom,\n tokenIndexTo\n );\n\n return dy;\n }\n\n /**\n * @notice Add liquidity to the pool\n * @param self Swap struct to read from and write to\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @return amount of LP token user received\n */\n function addLiquidity(\n Swap storage self,\n uint256[] memory amounts,\n uint256 minToMint\n ) external returns (uint256) {\n require(\n amounts.length == self.pooledTokens.length,\n \"Amounts must match pooled tokens\"\n );\n\n uint256[] memory fees = new uint256[](self.pooledTokens.length);\n uint256 lpTotalSupply = self.lpToken.totalSupply();\n // current state\n AddLiquidityInfo memory v = AddLiquidityInfo(0, 0, 0, 0);\n\n if (lpTotalSupply != 0) {\n v.d0 = getD(self);\n }\n uint256[] memory newBalances = self.balances;\n\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n require(\n lpTotalSupply != 0 || amounts[i] > 0,\n \"Must supply all tokens in pool\"\n );\n\n // Transfer tokens first to see if a fee was charged on transfer\n if (amounts[i] != 0) {\n uint256 beforeBalance =\n self.pooledTokens[i].balanceOf(address(this));\n self.pooledTokens[i].safeTransferFrom(\n msg.sender,\n address(this),\n amounts[i]\n );\n\n // Update the amounts[] with actual transfer amount\n amounts[i] = self.pooledTokens[i].balanceOf(address(this)).sub(\n beforeBalance\n );\n }\n\n newBalances[i] = self.balances[i].add(amounts[i]);\n }\n\n // invariant after change\n v.preciseA = _getAPrecise(self);\n v.d1 = getD(_xp(self, newBalances), v.preciseA);\n require(v.d1 > v.d0, \"D should increase\");\n\n // updated to reflect fees and calculate the user's LP tokens\n v.d2 = v.d1;\n if (lpTotalSupply != 0) {\n uint256 feePerToken = _feePerToken(self);\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(self.balances[i]).div(v.d0);\n fees[i] = feePerToken\n .mul(idealBalance.difference(newBalances[i]))\n .div(FEE_DENOMINATOR);\n self.balances[i] = newBalances[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n newBalances[i] = newBalances[i].sub(fees[i]);\n }\n v.d2 = getD(_xp(self, newBalances), v.preciseA);\n } else {\n // the initial depositor doesn't pay fees\n self.balances = newBalances;\n }\n\n uint256 toMint;\n uint256 toMintFee;\n uint256 toMintUser;\n if (lpTotalSupply == 0) {\n toMint = v.d1;\n } else {\n toMint = v.d2.sub(v.d0).mul(lpTotalSupply).div(v.d0);\n }\n\n require(toMint >= minToMint, \"Couldn't mint min requested\");\n // if deposit fee is none, mint full amount\n if (self.defaultDepositFee == 0) {\n self.lpToken.mint(msg.sender, toMint);\n } else {\n // mint the user's LP tokens minus the deposit fee\n toMintFee = toMint.mul(self.defaultDepositFee).div(FEE_DENOMINATOR);\n toMintUser = toMint.sub(toMintFee);\n self.lpToken.mint(self.devaddr, toMintFee);\n self.lpToken.mint(msg.sender, toMintUser);\n }\n \n emit AddLiquidity(\n msg.sender,\n amounts,\n fees,\n v.d1,\n lpTotalSupply + toMint\n );\n\n return toMint;\n }\n\n /**\n * @notice Update the withdraw fee for `user`. If the user is currently\n * not providing liquidity in the pool, sets to default value. If not, recalculate\n * the starting withdraw fee based on the last deposit's time & amount relative\n * to the new deposit.\n *\n * @param self Swap struct to read from and write to\n * @param user address of the user depositing tokens\n * @param toMint amount of pool tokens to be minted\n */\n function updateUserWithdrawFee(\n Swap storage self,\n address user,\n uint256 toMint\n ) external {\n _updateUserWithdrawFee(self, user, toMint);\n }\n\n function _updateUserWithdrawFee(\n Swap storage self,\n address user,\n uint256 toMint\n ) internal {\n // If token is transferred to address 0 (or burned), don't update the fee.\n if (user == address(0)) {\n return;\n }\n if (self.defaultWithdrawFee == 0) {\n // If current fee is set to 0%, set multiplier to FEE_DENOMINATOR\n self.withdrawFeeMultiplier[user] = FEE_DENOMINATOR;\n } else {\n // Otherwise, calculate appropriate discount based on last deposit amount\n uint256 currentFee = calculateCurrentWithdrawFee(self, user);\n uint256 currentBalance = self.lpToken.balanceOf(user);\n\n // ((currentBalance * currentFee) + (toMint * defaultWithdrawFee)) * FEE_DENOMINATOR /\n // ((toMint + currentBalance) * defaultWithdrawFee)\n self.withdrawFeeMultiplier[user] = currentBalance\n .mul(currentFee)\n .add(toMint.mul(self.defaultWithdrawFee))\n .mul(FEE_DENOMINATOR)\n .div(toMint.add(currentBalance).mul(self.defaultWithdrawFee));\n }\n self.depositTimestamp[user] = block.timestamp;\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param self Swap struct to read from and write to\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @return amounts of tokens the user received\n */\n function removeLiquidity(\n Swap storage self,\n uint256 amount,\n uint256[] calldata minAmounts\n ) external returns (uint256[] memory) {\n require(amount <= self.lpToken.balanceOf(msg.sender), \">LP.balanceOf\");\n require(\n minAmounts.length == self.pooledTokens.length,\n \"minAmounts must match poolTokens\"\n );\n\n uint256[] memory amounts =\n _calculateRemoveLiquidity(self, msg.sender, amount);\n\n for (uint256 i = 0; i < amounts.length; i++) {\n require(amounts[i] >= minAmounts[i], \"amounts[i] < minAmounts[i]\");\n self.balances[i] = self.balances[i].sub(amounts[i]);\n self.pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n self.lpToken.burnFrom(msg.sender, amount);\n\n emit RemoveLiquidity(msg.sender, amounts, self.lpToken.totalSupply());\n\n return amounts;\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token.\n * @param self Swap struct to read from and write to\n * @param tokenAmount the amount of the lp tokens to burn\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @return amount chosen token that user received\n */\n function removeLiquidityOneToken(\n Swap storage self,\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount\n ) external returns (uint256) {\n uint256 totalSupply = self.lpToken.totalSupply();\n uint256 numTokens = self.pooledTokens.length;\n require(\n tokenAmount <= self.lpToken.balanceOf(msg.sender),\n \">LP.balanceOf\"\n );\n require(tokenIndex < numTokens, \"Token not found\");\n\n uint256 dyFee;\n uint256 dy;\n\n (dy, dyFee) = calculateWithdrawOneToken(\n self,\n msg.sender,\n tokenAmount,\n tokenIndex\n );\n\n require(dy >= minAmount, \"dy < minAmount\");\n\n self.balances[tokenIndex] = self.balances[tokenIndex].sub(\n dy.add(dyFee.mul(self.adminFee).div(FEE_DENOMINATOR))\n );\n self.lpToken.burnFrom(msg.sender, tokenAmount);\n self.pooledTokens[tokenIndex].safeTransfer(msg.sender, dy);\n\n emit RemoveLiquidityOne(\n msg.sender,\n tokenAmount,\n totalSupply,\n tokenIndex,\n dy\n );\n\n return dy;\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances.\n *\n * @param self Swap struct to read from and write to\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @return actual amount of LP tokens burned in the withdrawal\n */\n function removeLiquidityImbalance(\n Swap storage self,\n uint256[] memory amounts,\n uint256 maxBurnAmount\n ) public returns (uint256) {\n require(\n amounts.length == self.pooledTokens.length,\n \"Amounts should match pool tokens\"\n );\n require(\n maxBurnAmount <= self.lpToken.balanceOf(msg.sender) &&\n maxBurnAmount != 0,\n \">LP.balanceOf\"\n );\n\n RemoveLiquidityImbalanceInfo memory v =\n RemoveLiquidityImbalanceInfo(0, 0, 0, 0);\n\n uint256 tokenSupply = self.lpToken.totalSupply();\n uint256 feePerToken = _feePerToken(self);\n\n uint256[] memory balances1 = self.balances;\n\n v.preciseA = _getAPrecise(self);\n v.d0 = getD(_xp(self), v.preciseA);\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n balances1[i] = balances1[i].sub(\n amounts[i],\n \"Cannot withdraw more than available\"\n );\n }\n v.d1 = getD(_xp(self, balances1), v.preciseA);\n uint256[] memory fees = new uint256[](self.pooledTokens.length);\n\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n uint256 idealBalance = v.d1.mul(self.balances[i]).div(v.d0);\n uint256 difference = idealBalance.difference(balances1[i]);\n fees[i] = feePerToken.mul(difference).div(FEE_DENOMINATOR);\n self.balances[i] = balances1[i].sub(\n fees[i].mul(self.adminFee).div(FEE_DENOMINATOR)\n );\n balances1[i] = balances1[i].sub(fees[i]);\n }\n\n v.d2 = getD(_xp(self, balances1), v.preciseA);\n\n uint256 tokenAmount = v.d0.sub(v.d2).mul(tokenSupply).div(v.d0);\n require(tokenAmount != 0, \"Burnt amount cannot be zero\");\n tokenAmount = tokenAmount.add(1).mul(FEE_DENOMINATOR).div(\n FEE_DENOMINATOR.sub(calculateCurrentWithdrawFee(self, msg.sender))\n );\n\n require(tokenAmount <= maxBurnAmount, \"tokenAmount > maxBurnAmount\");\n\n self.lpToken.burnFrom(msg.sender, tokenAmount);\n\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n self.pooledTokens[i].safeTransfer(msg.sender, amounts[i]);\n }\n\n emit RemoveLiquidityImbalance(\n msg.sender,\n amounts,\n fees,\n v.d1,\n tokenSupply.sub(tokenAmount)\n );\n\n return tokenAmount;\n }\n\n /**\n * @notice withdraw all admin fees to a given address\n * @param self Swap struct to withdraw fees from\n * @param to Address to send the fees to\n */\n function withdrawAdminFees(Swap storage self, address to) external {\n for (uint256 i = 0; i < self.pooledTokens.length; i++) {\n IERC20 token = self.pooledTokens[i];\n uint256 balance =\n token.balanceOf(address(this)).sub(self.balances[i]);\n if (balance != 0) {\n token.safeTransfer(to, balance);\n }\n }\n }\n\n /**\n * @notice Sets the admin fee\n * @dev adminFee cannot be higher than 100% of the swap fee\n * @param self Swap struct to update\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(Swap storage self, uint256 newAdminFee) external {\n require(newAdminFee <= MAX_ADMIN_FEE, \"Fee is too high\");\n self.adminFee = newAdminFee;\n\n emit NewAdminFee(newAdminFee);\n }\n\n /**\n * @notice update the swap fee\n * @dev fee cannot be higher than 1% of each swap\n * @param self Swap struct to update\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(Swap storage self, uint256 newSwapFee) external {\n require(newSwapFee <= MAX_SWAP_FEE, \"Fee is too high\");\n self.swapFee = newSwapFee;\n\n emit NewSwapFee(newSwapFee);\n }\n\n /**\n * @notice update the default withdraw fee. This also affects deposits made in the past as well.\n * @param self Swap struct to update\n * @param newWithdrawFee new withdraw fee to be applied\n */\n function setDefaultWithdrawFee(Swap storage self, uint256 newWithdrawFee)\n external\n {\n require(newWithdrawFee <= MAX_WITHDRAW_FEE, \"Fee is too high\");\n self.defaultWithdrawFee = newWithdrawFee;\n\n emit NewWithdrawFee(newWithdrawFee);\n }\n\n /**\n * @notice update the default deposit fee. \n * @param self Swap struct to update\n * @param newDepositFee new deposit fee to be applied\n */\n function setDefaultDepositFee(Swap storage self, uint256 newDepositFee)\n external\n {\n require(newDepositFee <= MAX_DEPOSIT_FEE, \"Fee is too high\");\n self.defaultDepositFee = newDepositFee;\n\n emit NewDepositFee(newDepositFee);\n }\n\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param self Swap struct to update\n * @param futureA_ the new A to ramp towards\n * @param futureTime_ timestamp when the new A should be reached\n */\n function rampA(\n Swap storage self,\n uint256 futureA_,\n uint256 futureTime_\n ) external {\n require(\n block.timestamp >= self.initialATime.add(1 days),\n \"Wait 1 day before starting ramp\"\n );\n require(\n futureTime_ >= block.timestamp.add(MIN_RAMP_TIME),\n \"Insufficient ramp time\"\n );\n require(\n futureA_ > 0 && futureA_ < MAX_A,\n \"futureA_ must be > 0 and < MAX_A\"\n );\n\n uint256 initialAPrecise = _getAPrecise(self);\n uint256 futureAPrecise = futureA_.mul(A_PRECISION);\n\n if (futureAPrecise < initialAPrecise) {\n require(\n futureAPrecise.mul(MAX_A_CHANGE) >= initialAPrecise,\n \"futureA_ is too small\"\n );\n } else {\n require(\n futureAPrecise <= initialAPrecise.mul(MAX_A_CHANGE),\n \"futureA_ is too large\"\n );\n }\n\n self.initialA = initialAPrecise;\n self.futureA = futureAPrecise;\n self.initialATime = block.timestamp;\n self.futureATime = futureTime_;\n\n emit RampA(\n initialAPrecise,\n futureAPrecise,\n block.timestamp,\n futureTime_\n );\n }\n\n /**\n * @notice Stops ramping A immediately. Once this function is called, rampA()\n * cannot be called for another 24 hours\n * @param self Swap struct to update\n */\n function stopRampA(Swap storage self) external {\n require(self.futureATime > block.timestamp, \"Ramp is already stopped\");\n uint256 currentA = _getAPrecise(self);\n\n self.initialA = currentA;\n self.futureA = currentA;\n self.initialATime = block.timestamp;\n self.futureATime = block.timestamp;\n\n emit StopRampA(currentA, block.timestamp);\n }\n\n function setDevAddress(Swap storage self, address _devaddr) public {\n require(msg.sender == self.devaddr, \"dev: wut?\");\n require(msg.sender != address(0), \"invalid address\");\n self.devaddr = _devaddr;\n }\n}\n\n// File: Swap.sol\n\n/**\n * @title Swap - A StableSwap implementation in solidity.\n * @notice This contract is responsible for custody of closely pegged assets (eg. group of stablecoins)\n * and automatic market making system. Users become an LP (Liquidity Provider) by depositing their tokens\n * in desired ratios for an exchange of the pool token that represents their share of the pool.\n * Users can burn pool tokens and withdraw their share of token(s).\n *\n * Each time a swap between the pooled tokens happens, a set fee incurs which effectively gets\n * distributed to the LPs.\n *\n * In case of emergencies, admin can pause additional deposits, swaps, or single-asset withdraws - which\n * stops the ratio of the tokens in the pool from changing.\n * Users can always withdraw their tokens via multi-asset withdraws.\n *\n * @dev Most of the logic is stored as a library `SwapUtils` for the sake of reducing contract's\n * deployment size.\n */\ncontract Swap is OwnerPausable, ReentrancyGuard {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n using MathUtils for uint256;\n using SwapUtils for SwapUtils.Swap;\n\n // Struct storing data responsible for automatic market maker functionalities. In order to\n // access this data, this contract uses SwapUtils library. For more details, see SwapUtils.sol\n SwapUtils.Swap public swapStorage;\n\n // Maps token address to an index in the pool. Used to prevent duplicate tokens in the pool.\n // getTokenIndex function also relies on this mapping to retrieve token index.\n mapping(address => uint8) private tokenIndexes;\n\n /*** EVENTS ***/\n\n // events replicated from SwapUtils to make the ABI easier for dumb\n // clients\n event TokenSwap(\n address indexed buyer,\n uint256 tokensSold,\n uint256 tokensBought,\n uint128 soldId,\n uint128 boughtId\n );\n event AddLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256 lpTokenSupply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 lpTokenAmount,\n uint256 lpTokenSupply,\n uint256 boughtId,\n uint256 tokensBought\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[] tokenAmounts,\n uint256[] fees,\n uint256 invariant,\n uint256 lpTokenSupply\n );\n event NewAdminFee(uint256 newAdminFee);\n event NewSwapFee(uint256 newSwapFee);\n event NewDepositFee(uint256 newDepositFee);\n event NewWithdrawFee(uint256 newWithdrawFee);\n event RampA(\n uint256 oldA,\n uint256 newA,\n uint256 initialTime,\n uint256 futureTime\n );\n event StopRampA(uint256 currentA, uint256 time);\n\n /**\n * @notice Deploys this Swap contract with given parameters as default\n * values. This will also deploy a LPToken that represents users\n * LP position. The owner of LPToken will be this contract - which means\n * only this contract is allowed to mint new tokens.\n *\n * @param _pooledTokens an array of ERC20s this pool will accept\n * @param decimals the decimals to use for each pooled token,\n * eg 8 for WBTC. Cannot be larger than POOL_PRECISION_DECIMALS\n * @param lpTokenName the long-form name of the token to be deployed\n * @param lpTokenSymbol the short symbol for the token to be deployed\n * @param _a the amplification coefficient * n * (n - 1). See the\n * StableSwap paper for details\n * @param _fee default swap fee to be initialized with\n * @param _adminFee default adminFee to be initialized with\n * @param _depositFee default depositFee to be initialized with\n * @param _withdrawFee default withdrawFee to be initialized with\n * @param _devaddr default _devaddr to be initialized with\n */\n constructor(\n IERC20[] memory _pooledTokens,\n uint8[] memory decimals,\n string memory lpTokenName,\n string memory lpTokenSymbol,\n uint256 _a,\n uint256 _fee,\n uint256 _adminFee,\n uint256 _depositFee,\n uint256 _withdrawFee,\n address _devaddr\n ) public OwnerPausable() ReentrancyGuard() {\n // Check _pooledTokens and precisions parameter\n require(_pooledTokens.length > 1, \"_pooledTokens.length <= 1\");\n require(_pooledTokens.length <= 32, \"_pooledTokens.length > 32\");\n require(\n _pooledTokens.length == decimals.length,\n \"_pooledTokens decimals mismatch\"\n );\n\n uint256[] memory precisionMultipliers = new uint256[](decimals.length);\n\n for (uint8 i = 0; i < _pooledTokens.length; i++) {\n if (i > 0) {\n // Check if index is already used. Check if 0th element is a duplicate.\n require(\n tokenIndexes[address(_pooledTokens[i])] == 0 &&\n _pooledTokens[0] != _pooledTokens[i],\n \"Duplicate tokens\"\n );\n }\n require(\n address(_pooledTokens[i]) != address(0),\n \"The 0 address isn't an ERC-20\"\n );\n require(\n decimals[i] <= SwapUtils.POOL_PRECISION_DECIMALS,\n \"Token decimals exceeds max\"\n );\n precisionMultipliers[i] =\n 10 **\n uint256(SwapUtils.POOL_PRECISION_DECIMALS).sub(\n uint256(decimals[i])\n );\n tokenIndexes[address(_pooledTokens[i])] = i;\n }\n\n // Check _a, _fee, _adminFee, _depositFee, _withdrawFee\n require(_a < SwapUtils.MAX_A, \"_a exceeds maximum\");\n require(_fee < SwapUtils.MAX_SWAP_FEE, \"_fee exceeds maximum\");\n require(\n _adminFee < SwapUtils.MAX_ADMIN_FEE,\n \"_adminFee exceeds maximum\"\n );\n require(\n _withdrawFee < SwapUtils.MAX_WITHDRAW_FEE,\n \"_withdrawFee exceeds maximum\"\n );\n require(\n _depositFee < SwapUtils.MAX_DEPOSIT_FEE,\n \"_depositFee exceeds maximum\"\n );\n\n // Initialize swapStorage struct\n swapStorage.lpToken = new LPToken(\n lpTokenName,\n lpTokenSymbol,\n SwapUtils.POOL_PRECISION_DECIMALS\n );\n swapStorage.pooledTokens = _pooledTokens;\n swapStorage.tokenPrecisionMultipliers = precisionMultipliers;\n swapStorage.balances = new uint256[](_pooledTokens.length);\n swapStorage.initialA = _a.mul(SwapUtils.A_PRECISION);\n swapStorage.futureA = _a.mul(SwapUtils.A_PRECISION);\n swapStorage.initialATime = 0;\n swapStorage.futureATime = 0;\n swapStorage.swapFee = _fee;\n swapStorage.adminFee = _adminFee;\n swapStorage.defaultDepositFee = _depositFee;\n swapStorage.defaultWithdrawFee = _withdrawFee;\n swapStorage.devaddr = _devaddr;\n\n }\n\n /*** MODIFIERS ***/\n\n /**\n * @notice Modifier to check deadline against current timestamp\n * @param deadline latest timestamp to accept this transaction\n */\n modifier deadlineCheck(uint256 deadline) {\n require(block.timestamp <= deadline, \"Deadline not met\");\n _;\n }\n\n /*** VIEW FUNCTIONS ***/\n\n /**\n * @notice Return A, the amplification coefficient * n * (n - 1)\n * @dev See the StableSwap paper for details\n * @return A parameter\n */\n function getA() external view returns (uint256) {\n return swapStorage.getA();\n }\n\n /**\n * @notice Return A in its raw precision form\n * @dev See the StableSwap paper for details\n * @return A parameter in its raw precision form\n */\n function getAPrecise() external view returns (uint256) {\n return swapStorage.getAPrecise();\n }\n\n /**\n * @notice Return address of the pooled token at given index. Reverts if tokenIndex is out of range.\n * @param index the index of the token\n * @return address of the token at given index\n */\n function getToken(uint8 index) public view returns (IERC20) {\n require(index < swapStorage.pooledTokens.length, \"Out of range\");\n return swapStorage.pooledTokens[index];\n }\n\n /**\n * @notice Return the index of the given token address. Reverts if no matching\n * token is found.\n * @param tokenAddress address of the token\n * @return the index of the given token address\n */\n function getTokenIndex(address tokenAddress) external view returns (uint8) {\n uint8 index = tokenIndexes[tokenAddress];\n require(\n address(getToken(index)) == tokenAddress,\n \"Token does not exist\"\n );\n return index;\n }\n\n /**\n * @notice Return timestamp of last deposit of given address\n * @return timestamp of the last deposit made by the given address\n */\n function getDepositTimestamp(address user) external view returns (uint256) {\n return swapStorage.getDepositTimestamp(user);\n }\n\n /**\n * @notice Return current balance of the pooled token at given index\n * @param index the index of the token\n * @return current balance of the pooled token at given index with token's native precision\n */\n function getTokenBalance(uint8 index) external view returns (uint256) {\n require(index < swapStorage.pooledTokens.length, \"Index out of range\");\n return swapStorage.balances[index];\n }\n\n /**\n * @notice Return balances of pooled tokens\n * @return current balances of all tokens in pool\n */\n function getBalances() external view returns (uint256[] memory) {\n return swapStorage.balances;\n }\n\n /**\n @notice Returns the swap fee\n @return current swap fee\n */\n function getSwapFee() external view returns (uint256) {\n return swapStorage.swapFee;\n }\n\n /**\n @notice Returns address of lp token\n @return address of lp token\n */\n function getLpToken() external view returns (address) {\n return address(swapStorage.lpToken);\n }\n\n /**\n * @notice Get the virtual price, to help calculate profit\n * @return the virtual price, scaled to the POOL_PRECISION_DECIMALS\n */\n function getVirtualPrice() external view returns (uint256) {\n return swapStorage.getVirtualPrice();\n }\n\n /**\n * @notice Calculate amount of tokens you receive on swap\n * @param tokenIndexFrom the token the user wants to sell\n * @param tokenIndexTo the token the user wants to buy\n * @param dx the amount of tokens the user wants to sell. If the token charges\n * a fee on transfers, use the amount that gets transferred after the fee.\n * @return amount of tokens the user will receive\n */\n function calculateSwap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx\n ) external view returns (uint256) {\n return swapStorage.calculateSwap(tokenIndexFrom, tokenIndexTo, dx);\n }\n\n /**\n * @notice A simple method to calculate prices from deposits or\n * withdrawals, excluding fees but including slippage. This is\n * helpful as an input into the various \"min\" parameters on calls\n * to fight front-running\n *\n * @dev This shouldn't be used outside frontends for user estimates.\n *\n * @param account address that is depositing or withdrawing tokens\n * @param amounts an array of token amounts to deposit or withdrawal,\n * corresponding to pooledTokens. The amount should be in each\n * pooled token's native precision. If a token charges a fee on transfers,\n * use the amount that gets transferred after the fee.\n * @param deposit whether this is a deposit or a withdrawal\n * @return token amount the user will receive\n */\n function calculateTokenAmount(\n address account,\n uint256[] calldata amounts,\n bool deposit\n ) external view returns (uint256) {\n return swapStorage.calculateTokenAmount(account, amounts, deposit);\n }\n\n /**\n * @notice A simple method to calculate amount of each underlying\n * tokens that is returned upon burning given amount of LP tokens\n * @param account the address that is withdrawing tokens\n * @param amount the amount of LP tokens that would be burned on withdrawal\n * @return array of token balances that the user will receive\n */\n function calculateRemoveLiquidity(address account, uint256 amount)\n external\n view\n returns (uint256[] memory)\n {\n return swapStorage.calculateRemoveLiquidity(account, amount);\n }\n\n /**\n * @notice Calculate the amount of underlying token available to withdraw\n * when withdrawing via only single token\n * @param account the address that is withdrawing tokens\n * @param tokenAmount the amount of LP token to burn\n * @param tokenIndex index of which token will be withdrawn\n * @return availableTokenAmount calculated amount of underlying token\n * available to withdraw\n */\n function calculateRemoveLiquidityOneToken(\n address account,\n uint256 tokenAmount,\n uint8 tokenIndex\n ) external view returns (uint256 availableTokenAmount) {\n (availableTokenAmount, ) = swapStorage.calculateWithdrawOneToken(\n account,\n tokenAmount,\n tokenIndex\n );\n }\n\n /**\n * @notice Calculate the fee that is applied when the given user withdraws. The withdraw fee\n * decays linearly over period of 4 weeks. For example, depositing and withdrawing right away\n * will charge you the full amount of withdraw fee. But withdrawing after 4 weeks will charge you\n * no additional fees.\n * @dev returned value should be divided by FEE_DENOMINATOR to convert to correct decimals\n * @param user address you want to calculate withdraw fee of\n * @return current withdraw fee of the user\n */\n function calculateCurrentWithdrawFee(address user)\n external\n view\n returns (uint256)\n {\n return swapStorage.calculateCurrentWithdrawFee(user);\n }\n\n /**\n * @notice This function reads the accumulated amount of admin fees of the token with given index\n * @param index Index of the pooled token\n * @return admin's token balance in the token's precision\n */\n function getAdminBalance(uint256 index) external view returns (uint256) {\n return swapStorage.getAdminBalance(index);\n }\n\n /*** STATE MODIFYING FUNCTIONS ***/\n\n /**\n * @notice Swap two tokens using this pool\n * @param tokenIndexFrom the token the user wants to swap from\n * @param tokenIndexTo the token the user wants to swap to\n * @param dx the amount of tokens the user wants to swap from\n * @param minDy the min amount the user would like to receive, or revert.\n * @param deadline latest timestamp to accept this transaction\n */\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n )\n external\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.swap(tokenIndexFrom, tokenIndexTo, dx, minDy);\n }\n\n /**\n * @notice Add liquidity to the pool with given amounts\n * @param amounts the amounts of each token to add, in their native precision\n * @param minToMint the minimum LP tokens adding this amount of liquidity\n * should mint, otherwise revert. Handy for front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP token user minted and received\n */\n function addLiquidity(\n uint256[] calldata amounts,\n uint256 minToMint,\n uint256 deadline\n )\n external\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.addLiquidity(amounts, minToMint);\n }\n\n /**\n * @notice Burn LP tokens to remove liquidity from the pool. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @dev Liquidity can always be removed, even when the pool is paused.\n * @param amount the amount of LP tokens to burn\n * @param minAmounts the minimum amounts of each token in the pool\n * acceptable for this burn. Useful as a front-running mitigation\n * @param deadline latest timestamp to accept this transaction\n * @return amounts of tokens user received\n */\n function removeLiquidity(\n uint256 amount,\n uint256[] calldata minAmounts,\n uint256 deadline\n ) external nonReentrant deadlineCheck(deadline) returns (uint256[] memory) {\n return swapStorage.removeLiquidity(amount, minAmounts);\n }\n\n /**\n * @notice Remove liquidity from the pool all in one token. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param tokenAmount the amount of the token you want to receive\n * @param tokenIndex the index of the token you want to receive\n * @param minAmount the minimum amount to withdraw, otherwise revert\n * @param deadline latest timestamp to accept this transaction\n * @return amount of chosen token user received\n */\n function removeLiquidityOneToken(\n uint256 tokenAmount,\n uint8 tokenIndex,\n uint256 minAmount,\n uint256 deadline\n )\n external\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return\n swapStorage.removeLiquidityOneToken(\n tokenAmount,\n tokenIndex,\n minAmount\n );\n }\n\n /**\n * @notice Remove liquidity from the pool, weighted differently than the\n * pool's current balances. Withdraw fee that decays linearly\n * over period of 4 weeks since last deposit will apply.\n * @param amounts how much of each token to withdraw\n * @param maxBurnAmount the max LP token provider is willing to pay to\n * remove liquidity. Useful as a front-running mitigation.\n * @param deadline latest timestamp to accept this transaction\n * @return amount of LP tokens burned\n */\n function removeLiquidityImbalance(\n uint256[] calldata amounts,\n uint256 maxBurnAmount,\n uint256 deadline\n )\n external\n nonReentrant\n whenNotPaused\n deadlineCheck(deadline)\n returns (uint256)\n {\n return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount);\n }\n\n /*** ADMIN FUNCTIONS ***/\n\n /**\n * @notice Updates the user withdraw fee. This function can only be called by\n * the pool token. Should be used to update the withdraw fee on transfer of pool tokens.\n * Transferring your pool token will reset the 4 weeks period. If the recipient is already\n * holding some pool tokens, the withdraw fee will be discounted in respective amounts.\n * @param recipient address of the recipient of pool token\n * @param transferAmount amount of pool token to transfer\n */\n function updateUserWithdrawFee(address recipient, uint256 transferAmount)\n external\n {\n require(\n msg.sender == address(swapStorage.lpToken),\n \"Only callable by pool token\"\n );\n swapStorage.updateUserWithdrawFee(recipient, transferAmount);\n }\n\n /**\n * @notice Withdraw all admin fees to the contract owner\n */\n function withdrawAdminFees() external onlyOwner {\n swapStorage.withdrawAdminFees(owner());\n }\n\n /**\n * @notice Update the admin fee. Admin fee takes portion of the swap fee.\n * @param newAdminFee new admin fee to be applied on future transactions\n */\n function setAdminFee(uint256 newAdminFee) external onlyOwner {\n swapStorage.setAdminFee(newAdminFee);\n }\n\n /**\n * @notice Update the swap fee to be applied on swaps\n * @param newSwapFee new swap fee to be applied on future transactions\n */\n function setSwapFee(uint256 newSwapFee) external onlyOwner {\n swapStorage.setSwapFee(newSwapFee);\n }\n\n /**\n * @notice Update the deposit fee. \n * @param newDepositFee new deposit fee to be applied on future deposits\n */\n function setDefaultDepositFee(uint256 newDepositFee) external onlyOwner {\n swapStorage.setDefaultDepositFee(newDepositFee);\n }\n\n /**\n * @notice Update the withdraw fee. This fee decays linearly over 4 weeks since\n * user's last deposit.\n * @param newWithdrawFee new withdraw fee to be applied on future deposits\n */\n function setDefaultWithdrawFee(uint256 newWithdrawFee) external onlyOwner {\n swapStorage.setDefaultWithdrawFee(newWithdrawFee);\n }\n\n /**\n * @notice Start ramping up or down A parameter towards given futureA and futureTime\n * Checks if the change is too rapid, and commits the new A value only when it falls under\n * the limit range.\n * @param futureA the new A to ramp towards\n * @param futureTime timestamp when the new A should be reached\n */\n function rampA(uint256 futureA, uint256 futureTime) external onlyOwner {\n swapStorage.rampA(futureA, futureTime);\n }\n\n /**\n * @notice Stop ramping A immediately. Reverts if ramp A is already stopped.\n */\n function stopRampA() external onlyOwner {\n swapStorage.stopRampA();\n }\n\n // Update dev address by the previous dev.\n function setDevAddress(address _devaddr) external onlyOwner {\n swapStorage.setDevAddress(_devaddr);\n }\n}\n", "contract_name": "Swap", "compiler_version": "0.6.12+commit.27d51765", "optimizer_enabled": true, "optimizer_runs": 200, "license_identifier": "MIT", "bytecode_len": 36224}