UNPKG

@zarclays/zswap-trident

Version:
80 lines 66.1 kB
{ "address": "0x2f686751b19a9d91cc3d57d90150Bc767f050066", "abi": [ { "inputs": [ { "internalType": "address", "name": "constantProductPoolFactory", "type": "address" }, { "internalType": "address[]", "name": "tokens", "type": "address[]" } ], "name": "getPoolsForTokens", "outputs": [ { "components": [ { "internalType": "uint8", "name": "tokenA", "type": "uint8" }, { "internalType": "uint8", "name": "tokenB", "type": "uint8" }, { "internalType": "uint112", "name": "reserve0", "type": "uint112" }, { "internalType": "uint112", "name": "reserve1", "type": "uint112" }, { "internalType": "uint16", "name": "swapFeeAndTwapSupport", "type": "uint16" } ], "internalType": "struct ConstantProductPoolFactoryHelper.ConstantProductPoolInfo[]", "name": "poolInfos", "type": "tuple[]" }, { "internalType": "uint256", "name": "length", "type": "uint256" } ], "stateMutability": "view", "type": "function" } ], "transactionHash": "0x16f543aa4fdeee885d6eaa4dc17757487dc00a42d5c0d20863ce7e9665d670ec", "receipt": { "to": null, "from": "0xf87BC5535602077d340806D71f805EA9907a843D", "contractAddress": "0x2f686751b19a9d91cc3d57d90150Bc767f050066", "transactionIndex": 0, "gasUsed": "681851", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockHash": "0xd97c500247bf2054b5dcb01aa4489649db721b1bfd43f30859ddd7e08f7b2d4f", "transactionHash": "0x16f543aa4fdeee885d6eaa4dc17757487dc00a42d5c0d20863ce7e9665d670ec", "logs": [], "blockNumber": 7464242, "cumulativeGasUsed": "681851", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, "solcInputHash": "76e6dc96ea94c96e1c2463853d56dcaa", "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"constantProductPoolFactory\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getPoolsForTokens\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"tokenA\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"tokenB\",\"type\":\"uint8\"},{\"internalType\":\"uint112\",\"name\":\"reserve0\",\"type\":\"uint112\"},{\"internalType\":\"uint112\",\"name\":\"reserve1\",\"type\":\"uint112\"},{\"internalType\":\"uint16\",\"name\":\"swapFeeAndTwapSupport\",\"type\":\"uint16\"}],\"internalType\":\"struct ConstantProductPoolFactoryHelper.ConstantProductPoolInfo[]\",\"name\":\"poolInfos\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Helper Contract for fetching info for several pools\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/pool/constant-product/ConstantProductPoolFactoryHelper.sol\":\"ConstantProductPoolFactoryHelper\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*///////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*///////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*///////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*///////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n bytes32 public constant PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*///////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\\n )\\n );\\n\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*///////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\",\"keccak256\":\"0x698cdbf614109fafc2bf00057b60715fa3aba9dad447c42f4f8b749ae16ce84f\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/utils/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Gas optimized reentrancy protection for smart contracts.\\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol)\\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)\\nabstract contract ReentrancyGuard {\\n uint256 private reentrancyStatus = 1;\\n\\n modifier nonReentrant() {\\n require(reentrancyStatus == 1, \\\"REENTRANCY\\\");\\n\\n reentrancyStatus = 2;\\n\\n _;\\n\\n reentrancyStatus = 1;\\n }\\n}\\n\",\"keccak256\":\"0x37da48458a348878d8db5b58367d734e340b9172ef947df430027638fc45a015\",\"license\":\"AGPL-3.0-only\"},\"contracts/abstract/PoolDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later-only\\n\\npragma solidity >=0.8.0;\\n\\n/// @dev Custom Errors\\nerror UnauthorisedDeployer();\\nerror ZeroAddress();\\nerror InvalidTokenOrder();\\n\\n/// @notice Trident pool deployer for whitelisted template factories.\\n/// @author Mudit Gupta.\\nabstract contract PoolDeployer {\\n address public immutable masterDeployer;\\n\\n mapping(address => mapping(address => address[])) public pools;\\n mapping(bytes32 => address) public configAddress;\\n\\n modifier onlyMaster() {\\n if (msg.sender != masterDeployer) revert UnauthorisedDeployer();\\n _;\\n }\\n\\n constructor(address _masterDeployer) {\\n if (_masterDeployer == address(0)) revert ZeroAddress();\\n masterDeployer = _masterDeployer;\\n }\\n\\n function _registerPool(\\n address pool,\\n address[] memory tokens,\\n bytes32 salt\\n ) internal onlyMaster {\\n // Store the address of the deployed contract.\\n configAddress[salt] = pool;\\n // Attacker used underflow, it was not very effective. poolimon!\\n // null token array would cause deployment to fail via out of bounds memory axis/gas limit.\\n unchecked {\\n for (uint256 i; i < tokens.length - 1; ++i) {\\n if (tokens[i] >= tokens[i + 1]) revert InvalidTokenOrder();\\n for (uint256 j = i + 1; j < tokens.length; ++j) {\\n pools[tokens[i]][tokens[j]].push(pool);\\n pools[tokens[j]][tokens[i]].push(pool);\\n }\\n }\\n }\\n }\\n\\n function poolsCount(address token0, address token1) external view returns (uint256 count) {\\n count = pools[token0][token1].length;\\n }\\n\\n function getPools(\\n address token0,\\n address token1,\\n uint256 startIndex,\\n uint256 count\\n ) external view returns (address[] memory pairPools) {\\n pairPools = new address[](count);\\n for (uint256 i = 0; i < count; i++) {\\n pairPools[i] = pools[token0][token1][startIndex + i];\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8e62e4204fe089b02a80330804cdc69aa3d6ae91d2ea7d371683ebf4aeacb817\",\"license\":\"GPL-3.0-or-later-only\"},\"contracts/interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../libraries/RebaseLibrary.sol\\\";\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe9dfcff95da3b487ff37f646aef14a998a36f90122fd5693096b5e3b14ea09af\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IConstantProductPoolFactory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"./IMasterDeployer.sol\\\";\\n\\ninterface IConstantProductPoolFactory {\\n function getDeployData() external view returns (bytes memory, IMasterDeployer);\\n}\\n\",\"keccak256\":\"0xf733168896197b23ffeee83630f9c90fb5e3c2ec6613de0f844e451f45985800\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMasterDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool deployer interface.\\ninterface IMasterDeployer {\\n function barFee() external view returns (uint256);\\n\\n function barFeeTo() external view returns (address);\\n\\n function bento() external view returns (address);\\n\\n function migrator() external view returns (address);\\n\\n function pools(address pool) external view returns (bool);\\n\\n function deployPool(address factory, bytes calldata deployData) external returns (address);\\n}\\n\",\"keccak256\":\"0x91c23deb7e4372faa35a0ae4ef6ccd684049aea7b2c75cf63009b28591b91cbc\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/ITridentCallee.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool callback interface.\\ninterface ITridentCallee {\\n function tridentSwapCallback(bytes calldata data) external;\\n\\n function tridentMintCallback(bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x256e838362a3064201b37b3b7c08bc1421b173a6fea633176123f0b827b868c9\",\"license\":\"GPL-3.0-or-later\"},\"contracts/libraries/RebaseLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity ^0.8;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa83360497e7e2a04332211832a8ceb41ef0301892fcf1b17174d7d4466782d44\",\"license\":\"GPL-3.0-or-later\"},\"contracts/libraries/TridentMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident sqrt helper library.\\nlibrary TridentMath {\\n /// @dev Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\\n function sqrt(uint256 x) internal pure returns (uint256 z) {\\n assembly {\\n // This segment is to get a reasonable initial estimate for the Babylonian method.\\n // If the initial estimate is bad, the number of correct bits increases ~linearly\\n // each iteration instead of ~quadratically.\\n // The idea is to get z*z*y within a small factor of x.\\n // More iterations here gets y in a tighter range. Currently, we will have\\n // y in [256, 256*2^16). We ensure y>= 256 so that the relative difference\\n // between y and y+1 is small. If x < 256 this is not possible, but those cases\\n // are easy enough to verify exhaustively.\\n z := 181 // The 'correct' value is 1, but this saves a multiply later\\n let y := x\\n // Note that we check y>= 2^(k + 8) but shift right by k bits each branch,\\n // this is to ensure that if x >= 256, then y >= 256.\\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\\n y := shr(128, y)\\n z := shl(64, z)\\n }\\n if iszero(lt(y, 0x1000000000000000000)) {\\n y := shr(64, y)\\n z := shl(32, z)\\n }\\n if iszero(lt(y, 0x10000000000)) {\\n y := shr(32, y)\\n z := shl(16, z)\\n }\\n if iszero(lt(y, 0x1000000)) {\\n y := shr(16, y)\\n z := shl(8, z)\\n }\\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8),\\n // and either y >= 256, or x < 256.\\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\\n\\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1)\\n // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s=1\\n // and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so\\n // that a is in [1/256, 256). Then we can estimate sqrt(y) as\\n // sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18\\n // There is no overflow risk here since y < 2^136 after the first branch above.\\n z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181\\n\\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\\n // Possibly with a quadratic/cubic polynomial above we could get 4-6.\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n z := shr(1, add(z, div(x, z)))\\n\\n // See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division.\\n // If x+1 is a perfect square, the Babylonian method cycles between\\n // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor.\\n // Since this case is rare, we choose to save gas on the assignment and\\n // repeat division in the rare case.\\n // If you don't care whether floor or ceil is returned, you can skip this.\\n if lt(div(x, z), z) {\\n z := div(x, z)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe46dce6bcd88a42bc841147b5e4df7176491d178b6c8af7a9525b36c0b826738\",\"license\":\"GPL-3.0-or-later\"},\"contracts/pool/constant-product/ConstantProductPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"@rari-capital/solmate/src/tokens/ERC20.sol\\\";\\nimport {ReentrancyGuard} from \\\"@rari-capital/solmate/src/utils/ReentrancyGuard.sol\\\";\\n\\nimport {IBentoBoxMinimal} from \\\"../../interfaces/IBentoBoxMinimal.sol\\\";\\nimport {IPool} from \\\"../../interfaces/IPool.sol\\\";\\nimport {ITridentCallee} from \\\"../../interfaces/ITridentCallee.sol\\\";\\nimport {IConstantProductPoolFactory} from \\\"../../interfaces/IConstantProductPoolFactory.sol\\\";\\nimport {IMasterDeployer} from \\\"../../interfaces/IMasterDeployer.sol\\\";\\n\\nimport {TridentMath} from \\\"../../libraries/TridentMath.sol\\\";\\n\\n/// @dev Custom Errors\\nerror ZeroAddress();\\nerror IdenticalAddress();\\nerror InvalidSwapFee();\\nerror InvalidAmounts();\\nerror InsufficientLiquidityMinted();\\nerror InvalidOutputToken();\\nerror InvalidInputToken();\\nerror PoolUninitialized();\\nerror InsufficientAmountIn();\\nerror Overflow();\\n\\n/// @notice Trident exchange pool template with constant product formula for swapping between an ERC-20 token pair.\\n/// @dev The reserves are stored as bento shares.\\n/// The curve is applied to shares as well. This pool does not care about the underlying amounts.\\ncontract ConstantProductPool is IPool, ERC20, ReentrancyGuard {\\n event Mint(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient);\\n event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient);\\n event Sync(uint256 reserve0, uint256 reserve1);\\n\\n uint256 internal constant MINIMUM_LIQUIDITY = 1000;\\n\\n uint8 internal constant PRECISION = 112;\\n uint256 internal constant MAX_FEE = 10000; // @dev 100%.\\n uint256 public immutable swapFee;\\n uint256 internal immutable MAX_FEE_MINUS_SWAP_FEE;\\n\\n IBentoBoxMinimal public immutable bento;\\n IMasterDeployer public immutable masterDeployer;\\n address public immutable token0;\\n address public immutable token1;\\n\\n uint256 public barFee;\\n address public barFeeTo;\\n uint256 public price0CumulativeLast;\\n uint256 public price1CumulativeLast;\\n uint256 public kLast;\\n\\n uint112 internal reserve0;\\n uint112 internal reserve1;\\n uint32 internal blockTimestampLast;\\n\\n bytes32 public constant override poolIdentifier = \\\"Trident:ConstantProduct\\\";\\n\\n constructor() ERC20(\\\"Sushi Constant Product LP Token\\\", \\\"SCPLP\\\", 18) {\\n (bytes memory _deployData, IMasterDeployer _masterDeployer) = IConstantProductPoolFactory(msg.sender).getDeployData();\\n\\n (address _token0, address _token1, uint256 _swapFee, bool _twapSupport) = abi.decode(\\n _deployData,\\n (address, address, uint256, bool)\\n );\\n\\n // Factory ensures that the tokens are sorted.\\n if (_token0 == address(0)) revert ZeroAddress();\\n if (_token0 == _token1) revert IdenticalAddress();\\n if (_swapFee > MAX_FEE) revert InvalidSwapFee();\\n\\n token0 = _token0;\\n token1 = _token1;\\n swapFee = _swapFee;\\n // This is safe from underflow - `swapFee` cannot exceed `MAX_FEE` per previous check.\\n unchecked {\\n MAX_FEE_MINUS_SWAP_FEE = MAX_FEE - _swapFee;\\n }\\n barFee = _masterDeployer.barFee();\\n barFeeTo = _masterDeployer.barFeeTo();\\n bento = IBentoBoxMinimal(_masterDeployer.bento());\\n masterDeployer = _masterDeployer;\\n if (_twapSupport) blockTimestampLast = uint32(block.timestamp);\\n }\\n\\n /// @dev Mints LP tokens - should be called via the router after transferring `bento` tokens.\\n /// The router must ensure that sufficient LP tokens are minted by using the return value.\\n function mint(bytes calldata data) public override nonReentrant returns (uint256 liquidity) {\\n address recipient = abi.decode(data, (address));\\n (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves();\\n (uint256 balance0, uint256 balance1) = _balance();\\n\\n uint256 computed = TridentMath.sqrt(balance0 * balance1);\\n uint256 amount0 = balance0 - _reserve0;\\n uint256 amount1 = balance1 - _reserve1;\\n\\n (uint256 fee0, uint256 fee1) = _nonOptimalMintFee(amount0, amount1, _reserve0, _reserve1);\\n _reserve0 += uint112(fee0);\\n _reserve1 += uint112(fee1);\\n\\n (uint256 _totalSupply, uint256 k) = _mintFee(_reserve0, _reserve1);\\n\\n if (_totalSupply == 0) {\\n if (amount0 == 0 || amount1 == 0) revert InvalidAmounts();\\n liquidity = computed - MINIMUM_LIQUIDITY;\\n _mint(address(0), MINIMUM_LIQUIDITY);\\n } else {\\n uint256 kIncrease;\\n unchecked {\\n kIncrease = computed - k;\\n }\\n liquidity = (kIncrease * _totalSupply) / k;\\n }\\n if (liquidity == 0) revert InsufficientLiquidityMinted();\\n _mint(recipient, liquidity);\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n kLast = computed;\\n emit Mint(msg.sender, amount0, amount1, recipient);\\n }\\n\\n /// @dev Burns LP tokens sent to this contract. The router must ensure that the user gets sufficient output tokens.\\n function burn(bytes calldata data) public override nonReentrant returns (IPool.TokenAmount[] memory withdrawnAmounts) {\\n (address recipient, bool unwrapBento) = abi.decode(data, (address, bool));\\n (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves();\\n (uint256 balance0, uint256 balance1) = _balance();\\n uint256 liquidity = balanceOf[address(this)];\\n\\n (uint256 _totalSupply, ) = _mintFee(_reserve0, _reserve1);\\n\\n uint256 amount0 = (liquidity * balance0) / _totalSupply;\\n uint256 amount1 = (liquidity * balance1) / _totalSupply;\\n\\n _burn(address(this), liquidity);\\n _transfer(token0, amount0, recipient, unwrapBento);\\n _transfer(token1, amount1, recipient, unwrapBento);\\n // This is safe from underflow - amounts are lesser figures derived from balances.\\n unchecked {\\n balance0 -= amount0;\\n balance1 -= amount1;\\n }\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n kLast = TridentMath.sqrt(balance0 * balance1);\\n\\n withdrawnAmounts = new TokenAmount[](2);\\n withdrawnAmounts[0] = TokenAmount({token: address(token0), amount: amount0});\\n withdrawnAmounts[1] = TokenAmount({token: address(token1), amount: amount1});\\n emit Burn(msg.sender, amount0, amount1, recipient);\\n }\\n\\n /// @dev Burns LP tokens sent to this contract and swaps one of the output tokens for another\\n /// - i.e., the user gets a single token out by burning LP tokens.\\n function burnSingle(bytes calldata data) public override nonReentrant returns (uint256 amountOut) {\\n (address tokenOut, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool));\\n (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves();\\n uint256 liquidity = balanceOf[address(this)];\\n\\n (uint256 _totalSupply, ) = _mintFee(_reserve0, _reserve1);\\n\\n uint256 amount0 = (liquidity * _reserve0) / _totalSupply;\\n uint256 amount1 = (liquidity * _reserve1) / _totalSupply;\\n\\n kLast = TridentMath.sqrt((_reserve0 - amount0) * (_reserve1 - amount1));\\n\\n _burn(address(this), liquidity);\\n\\n // Swap one token for another\\n unchecked {\\n if (tokenOut == token1) {\\n // Swap `token0` for `token1`\\n // - calculate `amountOut` as if the user first withdrew balanced liquidity and then swapped `token0` for `token1`.\\n amount1 += _getAmountOut(amount0, _reserve0 - amount0, _reserve1 - amount1);\\n _transfer(token1, amount1, recipient, unwrapBento);\\n amountOut = amount1;\\n amount0 = 0;\\n } else {\\n // Swap `token1` for `token0`.\\n if (tokenOut != token0) revert InvalidOutputToken();\\n amount0 += _getAmountOut(amount1, _reserve1 - amount1, _reserve0 - amount0);\\n _transfer(token0, amount0, recipient, unwrapBento);\\n amountOut = amount0;\\n amount1 = 0;\\n }\\n }\\n\\n (uint256 balance0, uint256 balance1) = _balance();\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n\\n emit Burn(msg.sender, amount0, amount1, recipient);\\n }\\n\\n /// @dev Swaps one token for another. The router must prefund this contract and ensure there isn't too much slippage.\\n function swap(bytes calldata data) public override nonReentrant returns (uint256 amountOut) {\\n (address tokenIn, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool));\\n (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves();\\n if (_reserve0 == 0) revert PoolUninitialized();\\n (uint256 balance0, uint256 balance1) = _balance();\\n uint256 amountIn;\\n address tokenOut;\\n unchecked {\\n if (tokenIn == token0) {\\n tokenOut = token1;\\n amountIn = balance0 - _reserve0;\\n amountOut = _getAmountOut(amountIn, _reserve0, _reserve1);\\n balance1 -= amountOut;\\n } else {\\n if (tokenIn != token1) revert InvalidInputToken();\\n tokenOut = token0;\\n amountIn = balance1 - reserve1;\\n amountOut = _getAmountOut(amountIn, _reserve1, _reserve0);\\n balance0 -= amountOut;\\n }\\n }\\n _transfer(tokenOut, amountOut, recipient, unwrapBento);\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n emit Swap(recipient, tokenIn, tokenOut, amountIn, amountOut);\\n }\\n\\n /// @dev Swaps one token for another. The router must support swap callbacks and ensure there isn't too much slippage.\\n function flashSwap(bytes calldata data) public override nonReentrant returns (uint256 amountOut) {\\n (address tokenIn, address recipient, bool unwrapBento, uint256 amountIn, bytes memory context) = abi.decode(\\n data,\\n (address, address, bool, uint256, bytes)\\n );\\n (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves();\\n if (_reserve0 == 0) revert PoolUninitialized();\\n unchecked {\\n if (tokenIn == token0) {\\n amountOut = _getAmountOut(amountIn, _reserve0, _reserve1);\\n _transfer(token1, amountOut, recipient, unwrapBento);\\n ITridentCallee(msg.sender).tridentSwapCallback(context);\\n (uint256 balance0, uint256 balance1) = _balance();\\n if (balance0 - _reserve0 < amountIn) revert InsufficientAmountIn();\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n emit Swap(recipient, tokenIn, token1, amountIn, amountOut);\\n } else {\\n if (tokenIn != token1) revert InvalidInputToken();\\n amountOut = _getAmountOut(amountIn, _reserve1, _reserve0);\\n _transfer(token0, amountOut, recipient, unwrapBento);\\n ITridentCallee(msg.sender).tridentSwapCallback(context);\\n (uint256 balance0, uint256 balance1) = _balance();\\n if (balance1 - _reserve1 < amountIn) revert InsufficientAmountIn();\\n _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast);\\n emit Swap(recipient, tokenIn, token0, amountIn, amountOut);\\n }\\n }\\n }\\n\\n /// @dev Updates `barFee` and `barFeeTo` for Trident protocol.\\n function updateBarParameters() public {\\n barFee = masterDeployer.barFee();\\n barFeeTo = masterDeployer.barFeeTo();\\n }\\n\\n function _getReserves()\\n internal\\n view\\n returns (\\n uint112 _reserve0,\\n uint112 _reserve1,\\n uint32 _blockTimestampLast\\n )\\n {\\n _reserve0 = reserve0;\\n _reserve1 = reserve1;\\n _blockTimestampLast = blockTimestampLast;\\n }\\n\\n function _balance() internal view returns (uint256 balance0, uint256 balance1) {\\n balance0 = bento.balanceOf(token0, address(this));\\n balance1 = bento.balanceOf(token1, address(this));\\n }\\n\\n function _update(\\n uint256 balance0,\\n uint256 balance1,\\n uint112 _reserve0,\\n uint112 _reserve1,\\n uint32 _blockTimestampLast\\n ) internal {\\n if (balance0 > type(uint112).max || balance1 > type(uint112).max) revert Overflow();\\n if (_blockTimestampLast == 0) {\\n // TWAP support is disabled for gas efficiency.\\n reserve0 = uint112(balance0);\\n reserve1 = uint112(balance1);\\n } else {\\n uint32 blockTimestamp = uint32(block.timestamp);\\n if (blockTimestamp != _blockTimestampLast && _reserve0 != 0 && _reserve1 != 0) {\\n unchecked {\\n uint32 timeElapsed = blockTimestamp - _blockTimestampLast;\\n uint256 price0 = (uint256(_reserve1) << PRECISION) / _reserve0;\\n price0CumulativeLast += price0 * timeElapsed;\\n uint256 price1 = (uint256(_reserve0) << PRECISION) / _reserve1;\\n price1CumulativeLast += price1 * timeElapsed;\\n }\\n }\\n reserve0 = uint112(balance0);\\n reserve1 = uint112(balance1);\\n blockTimestampLast = blockTimestamp;\\n }\\n emit Sync(balance0, balance1);\\n }\\n\\n function _mintFee(uint112 _reserve0, uint112 _reserve1) internal returns (uint256 _totalSupply, uint256 computed) {\\n _totalSupply = totalSupply;\\n uint256 _kLast = kLast;\\n if (_kLast != 0) {\\n computed = TridentMath.sqrt(uint256(_reserve0) * _reserve1);\\n if (computed > _kLast) {\\n // `barFee` % of increase in liquidity.\\n uint256 _barFee = barFee;\\n uint256 numerator = _totalSupply * (computed - _kLast) * _barFee;\\n uint256 denominator = (MAX_FEE - _barFee) * computed + _barFee * _kLast;\\n uint256 liquidity = numerator / denominator;\\n\\n if (liquidity != 0) {\\n _mint(barFeeTo, liquidity);\\n _totalSupply += liquidity;\\n }\\n }\\n }\\n }\\n\\n function _getAmountOut(\\n uint256 amountIn,\\n uint256 reserveAmountIn,\\n uint256 reserveAmountOut\\n ) internal view returns (uint256 amountOut) {\\n uint256 amountInWithFee = amountIn * MAX_FEE_MINUS_SWAP_FEE;\\n amountOut = (amountInWithFee * reserveAmountOut) / (reserveAmountIn * MAX_FEE + amountInWithFee);\\n }\\n\\n function _getAmountIn(\\n uint256 amountOut,\\n uint256 reserveAmountIn,\\n uint256 reserveAmountOut\\n ) internal view returns (uint256 amountIn) {\\n amountIn = (reserveAmountIn * amountOut * MAX_FEE) / ((reserveAmountOut - amountOut) * MAX_FEE_MINUS_SWAP_FEE) + 1;\\n }\\n\\n function _transfer(\\n address token,\\n uint256 shares,\\n address to,\\n bool unwrapBento\\n ) internal {\\n if (unwrapBento) {\\n bento.withdraw(token, address(this), to, 0, shares);\\n } else {\\n bento.transfer(token, address(this), to, shares);\\n }\\n }\\n\\n /// @dev This fee is charged to cover for `swapFee` when users add unbalanced liquidity.\\n function _nonOptimalMintFee(\\n uint256 _amount0,\\n uint256 _amount1,\\n uint256 _reserve0,\\n uint256 _reserve1\\n ) internal view returns (uint256 token0Fee, uint256 token1Fee) {\\n if (_reserve0 == 0 || _reserve1 == 0) return (0, 0);\\n uint256 amount1Optimal = (_amount0 * _reserve1) / _reserve0;\\n if (amount1Optimal <= _amount1) {\\n token1Fee = (swapFee * (_amount1 - amount1Optimal)) / (2 * MAX_FEE);\\n } else {\\n uint256 amount0Optimal = (_amount1 * _reserve0) / _reserve1;\\n token0Fee = (swapFee * (_amount0 - amount0Optimal)) / (2 * MAX_FEE);\\n }\\n }\\n\\n function getAssets() public view override returns (address[] memory assets) {\\n assets = new address[](2);\\n assets[0] = token0;\\n assets[1] = token1;\\n }\\n\\n function getAmountOut(bytes calldata data) public view override returns (uint256 finalAmountOut) {\\n (address tokenIn, uint256 amountIn) = abi.decode(data, (address, uint256));\\n (uint112 _reserve0, uint112 _reserve1, ) = _getReserves();\\n if (tokenIn == token0) {\\n finalAmountOut = _getAmountOut(amountIn, _reserve0, _reserve1);\\n } else {\\n if (tokenIn != token1) revert InvalidInputToken();\\n finalAmountOut = _getAmountOut(amountIn, _reserve1, _reserve0);\\n }\\n }\\n\\n function getAmountIn(bytes calldata data) public view override returns (uint256 finalAmountIn) {\\n (address tokenOut, uint256 amountOut) = abi.decode(data, (address, uint256));\\n (uint112 _reserve0, uint112 _reserve1, ) = _getReserves();\\n if (tokenOut == token1) {\\n finalAmountIn = _getAmountIn(amountOut, _reserve0, _reserve1);\\n } else {\\n if (tokenOut != token0) revert InvalidOutputToken();\\n finalAmountIn = _getAmountIn(amountOut, _reserve1, _reserve0);\\n }\\n }\\n\\n /// @dev Returned values are in terms of BentoBox \\\"shares\\\".\\n function getReserves()\\n public\\n view\\n returns (\\n uint112 _reserve0,\\n uint112 _reserve1,\\n uint32 _blockTimestampLast\\n )\\n {\\n return _getReserves();\\n }\\n\\n /// @dev Returned values are the native ERC20 token amounts.\\n function getNativeReserves()\\n public\\n view\\n returns (\\n uint256 _nativeReserve0,\\n uint256 _nativeReserve1,\\n uint32 _blockTimestampLast\\n )\\n {\\n (uint112 _reserve0, uint112 _reserve1, uint32 __blockTimestampLast) = _getReserves();\\n _nativeReserve0 = bento.toAmount(token0, _reserve0, false);\\n _nativeReserve1 = bento.toAmount(token1, _reserve1, false);\\n _blockTimestampLast = __blockTimestampLast;\\n }\\n}\\n\",\"keccak256\":\"0x5f0a882fc3cf76d885bebfc53e600a580a7705e9b3ee4b5e90144d36797e2053\",\"license\":\"GPL-3.0-or-later\"},\"contracts/pool/constant-product/ConstantProductPoolFactory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport {PoolDeployer} from \\\"../../abstract/PoolDeployer.sol\\\";\\nimport {ConstantProductPool} from \\\"./ConstantProductPool.sol\\\";\\nimport {IConstantProductPoolFactory} from \\\"../../interfaces/IConstantProductPoolFactory.sol\\\";\\nimport {IMasterDeployer} from \\\"../../interfaces/IMasterDeployer.sol\\\";\\n\\n/// @notice Contract for deploying Trident exchange Constant Product Pool with configurations.\\n/// @author Mudit Gupta.\\ncontract ConstantProductPoolFactory is IConstantProductPoolFactory, PoolDeployer {\\n bytes32 public constant bytecodeHash = keccak256(type(ConstantProductPool).creationCode);\\n\\n bytes private cachedDeployData;\\n\\n constructor(address _masterDeployer) PoolDeployer(_masterDeployer) {}\\n\\n function deployPool(bytes memory _deployData) external returns (address pool) {\\n (address tokenA, address tokenB, uint256 swapFee, bool twapSupport) = abi.decode(_deployData, (address, address, uint256, bool));\\n\\n if (tokenA > tokenB) {\\n (tokenA, tokenB) = (tokenB, tokenA);\\n }\\n\\n // Strips any extra data.