{
  "address": "0x70e9D5279AFbf898FB507C6FfF8Dd92618e892DB",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "contract IBentoBoxMinimal",
          "name": "bento",
          "type": "address"
        },
        {
          "internalType": "contract IMasterDeployer",
          "name": "masterDeployer",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "wETH",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "PermitFailed",
      "type": "error"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "token",
              "type": "address"
            },
            {
              "internalType": "bool",
              "name": "native",
              "type": "bool"
            },
            {
              "internalType": "uint256",
              "name": "amount",
              "type": "uint256"
            }
          ],
          "internalType": "struct ITridentRouter.TokenInput[]",
          "name": "tokenInput",
          "type": "tuple[]"
        },
        {
          "internalType": "address",
          "name": "pool",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "minLiquidity",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "addLiquidity",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "liquidity",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "pool",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "minLiquidity",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "addLiquidityLazy",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "liquidity",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "approveMasterContract",
      "outputs": [],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes[]",
          "name": "data",
          "type": "bytes[]"
        }
      ],
      "name": "batch",
      "outputs": [
        {
          "internalType": "bytes[]",
          "name": "results",
          "type": "bytes[]"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "bento",
      "outputs": [
        {
          "internalType": "contract IBentoBoxMinimal",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "pool",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "liquidity",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        },
        {
          "components": [
            {
              "internalType": "address",
              "name": "token",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "amount",
              "type": "uint256"
            }
          ],
          "internalType": "struct IPool.TokenAmount[]",
          "name": "minWithdrawals",
          "type": "tuple[]"
        }
      ],
      "name": "burnLiquidity",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "pool",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "liquidity",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        },
        {
          "internalType": "uint256",
          "name": "minWithdrawal",
          "type": "uint256"
        }
      ],
      "name": "burnLiquiditySingle",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "tokenIn",
                  "type": "address"
                },
                {
                  "internalType": "address",
                  "name": "pool",
                  "type": "address"
                },
                {
                  "internalType": "bool",
                  "name": "native",
                  "type": "bool"
                },
                {
                  "internalType": "uint256",
                  "name": "amount",
                  "type": "uint256"
                },
                {
                  "internalType": "bytes",
                  "name": "data",
                  "type": "bytes"
                }
              ],
              "internalType": "struct ITridentRouter.InitialPath[]",
              "name": "initialPath",
              "type": "tuple[]"
            },
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "tokenIn",
                  "type": "address"
                },
                {
                  "internalType": "address",
                  "name": "pool",
                  "type": "address"
                },
                {
                  "internalType": "uint64",
                  "name": "balancePercentage",
                  "type": "uint64"
                },
                {
                  "internalType": "bytes",
                  "name": "data",
                  "type": "bytes"
                }
              ],
              "internalType": "struct ITridentRouter.PercentagePath[]",
              "name": "percentagePath",
              "type": "tuple[]"
            },
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "token",
                  "type": "address"
                },
                {
                  "internalType": "address",
                  "name": "to",
                  "type": "address"
                },
                {
                  "internalType": "bool",
                  "name": "unwrapBento",
                  "type": "bool"
                },
                {
                  "internalType": "uint256",
                  "name": "minAmount",
                  "type": "uint256"
                }
              ],
              "internalType": "struct ITridentRouter.Output[]",
              "name": "output",
              "type": "tuple[]"
            }
          ],
          "internalType": "struct ITridentRouter.ComplexPathParams",
          "name": "params",
          "type": "tuple"
        }
      ],
      "name": "complexPath",
      "outputs": [],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "factory",
          "type": "address"
        },
        {
          "internalType": "bytes",
          "name": "deployData",
          "type": "bytes"
        }
      ],
      "name": "deployPool",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "tokenIn",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "amountIn",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountOutMinimum",
              "type": "uint256"
            },
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "pool",
                  "type": "address"
                },
                {
                  "internalType": "bytes",
                  "name": "data",
                  "type": "bytes"
                }
              ],
              "internalType": "struct ITridentRouter.Path[]",
              "name": "path",
              "type": "tuple[]"
            }
          ],
          "internalType": "struct ITridentRouter.ExactInputParams",
          "name": "params",
          "type": "tuple"
        }
      ],
      "name": "exactInput",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountOut",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amountOutMinimum",
          "type": "uint256"
        },
        {
          "components": [
            {
              "internalType": "address",
              "name": "pool",
              "type": "address"
            },
            {
              "internalType": "bytes",
              "name": "data",
              "type": "bytes"
            }
          ],
          "internalType": "struct ITridentRouter.Path[]",
          "name": "path",
          "type": "tuple[]"
        }
      ],
      "name": "exactInputLazy",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountOut",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "amountIn",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountOutMinimum",
              "type": "uint256"
            },
            {
              "internalType": "address",
              "name": "pool",
              "type": "address"
            },
            {
              "internalType": "address",
              "name": "tokenIn",
              "type": "address"
            },
            {
              "internalType": "bytes",
              "name": "data",
              "type": "bytes"
            }
          ],
          "internalType": "struct ITridentRouter.ExactInputSingleParams",
          "name": "params",
          "type": "tuple"
        }
      ],
      "name": "exactInputSingle",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountOut",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "amountIn",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountOutMinimum",
              "type": "uint256"
            },
            {
              "internalType": "address",
              "name": "pool",
              "type": "address"
            },
            {
              "internalType": "address",
              "name": "tokenIn",
              "type": "address"
            },
            {
              "internalType": "bytes",
              "name": "data",
              "type": "bytes"
            }
          ],
          "internalType": "struct ITridentRouter.ExactInputSingleParams",
          "name": "params",
          "type": "tuple"
        }
      ],
      "name": "exactInputSingleWithNativeToken",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountOut",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "tokenIn",
              "type": "address"
            },
            {
              "internalType": "uint256",
              "name": "amountIn",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountOutMinimum",
              "type": "uint256"
            },
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "pool",
                  "type": "address"
                },
                {
                  "internalType": "bytes",
                  "name": "data",
                  "type": "bytes"
                }
              ],
              "internalType": "struct ITridentRouter.Path[]",
              "name": "path",
              "type": "tuple[]"
            }
          ],
          "internalType": "struct ITridentRouter.ExactInputParams",
          "name": "params",
          "type": "tuple"
        }
      ],
      "name": "exactInputWithNativeToken",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountOut",
          "type": "uint256"
        }
      ],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "masterDeployer",
      "outputs": [
        {
          "internalType": "contract IMasterDeployer",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "deadline",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "permitThis",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "nonce",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "expiry",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "permitThisAllowed",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "refundETH",
      "outputs": [],
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        }
      ],
      "name": "sweepBentoBoxToken",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        }
      ],
      "name": "sweepNativeToken",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "tridentMintCallback",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "tridentSwapCallback",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amountMinimum",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        }
      ],
      "name": "unwrapWETH",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "stateMutability": "payable",
      "type": "receive"
    }
  ],
  "transactionHash": "0xfb844da6dc15875d5718b10a75ad229c8d423fa197bbec0475e02d694fe7ff46",
  "receipt": {
    "to": null,
    "from": "0x58B4B6951e9174F153635574076241315D7d3503",
    "contractAddress": "0x70e9D5279AFbf898FB507C6FfF8Dd92618e892DB",
    "transactionIndex": 0,
    "gasUsed": "4114089",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000020000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000080000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000080000002000000000000000000000000000",
    "blockHash": "0x3416079ebcb6ca635c299e534487a29dd3ac1330bfd20d24b7f8679df857fe8f",
    "transactionHash": "0xfb844da6dc15875d5718b10a75ad229c8d423fa197bbec0475e02d694fe7ff46",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 28501086,
        "transactionHash": "0xfb844da6dc15875d5718b10a75ad229c8d423fa197bbec0475e02d694fe7ff46",
        "address": "0xc381a85ed7C7448Da073b7d6C9d4cBf1Cbf576f0",
        "topics": [
          "0xdfb44ffabf0d3a8f650d3ce43eff98f6d050e7ea1a396d5794f014e7dadabacb",
          "0x00000000000000000000000070e9d5279afbf898fb507c6fff8dd92618e892db"
        ],
        "data": "0x",
        "logIndex": 0,
        "blockHash": "0x3416079ebcb6ca635c299e534487a29dd3ac1330bfd20d24b7f8679df857fe8f"
      }
    ],
    "blockNumber": 28501086,
    "cumulativeGasUsed": "4114089",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0xc381a85ed7C7448Da073b7d6C9d4cBf1Cbf576f0",
    "0xdCFaae69E67E4bA73d5A890Fcae097eB3C615e96",
    "0xd0A1E359811322d97991E03f863a0C30C2cF029C"
  ],
  "solcInputHash": "221cdcc428dc8b1c66e6b7265c8da82a",
  "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"bento\",\"type\":\"address\"},{\"internalType\":\"contract IMasterDeployer\",\"name\":\"masterDeployer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wETH\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"PermitFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"native\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct ITridentRouter.TokenInput[]\",\"name\":\"tokenInput\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidity\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidity\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"addLiquidityLazy\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"approveMasterContract\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"batch\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bento\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct IPool.TokenAmount[]\",\"name\":\"minWithdrawals\",\"type\":\"tuple[]\"}],\"name\":\"burnLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"minWithdrawal\",\"type\":\"uint256\"}],\"name\":\"burnLiquiditySingle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"native\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.InitialPath[]\",\"name\":\"initialPath\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"balancePercentage\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.PercentagePath[]\",\"name\":\"percentagePath\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"unwrapBento\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct ITridentRouter.Output[]\",\"name\":\"output\",\"type\":\"tuple[]\"}],\"internalType\":\"struct ITridentRouter.ComplexPathParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"complexPath\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"deployData\",\"type\":\"bytes\"}],\"name\":\"deployPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.Path[]\",\"name\":\"path\",\"type\":\"tuple[]\"}],\"internalType\":\"struct ITridentRouter.ExactInputParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.Path[]\",\"name\":\"path\",\"type\":\"tuple[]\"}],\"name\":\"exactInputLazy\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.ExactInputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInputSingle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.ExactInputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInputSingleWithNativeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"struct ITridentRouter.Path[]\",\"name\":\"path\",\"type\":\"tuple[]\"}],\"internalType\":\"struct ITridentRouter.ExactInputParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInputWithNativeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterDeployer\",\"outputs\":[{\"internalType\":\"contract IMasterDeployer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permitThis\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permitThisAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"refundETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepBentoBoxToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepNativeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"tridentMintCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"tridentSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"unwrapWETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addLiquidity((address,bool,uint256)[],address,uint256,bytes)\":{\"params\":{\"data\":\"Data required by the pool to add liquidity.\",\"minLiquidity\":\"Minimum output liquidity - caps slippage.\",\"pool\":\"Pool address to add liquidity to.\",\"tokenInput\":\"Token address and amount to add as liquidity.\"}},\"addLiquidityLazy(address,uint256,bytes)\":{\"details\":\"The input tokens are sent to the pool during the callback.\"},\"batch(bytes[])\":{\"details\":\"The `msg.value` should not be trusted for any method callable from this function.Uses a modified version of the batch function - preventing multiple calls of the single input swap functions\",\"params\":{\"data\":\"ABI-encoded params for each of the calls to make to this contract.\"},\"returns\":{\"results\":\"The results from each of the calls passed in via `data`.\"}},\"burnLiquidity(address,uint256,bytes,(address,uint256)[])\":{\"params\":{\"data\":\"Data required by the pool to burn liquidity.\",\"liquidity\":\"Amount of liquidity tokens to burn.\",\"minWithdrawals\":\"Minimum amount of `bento` tokens to be returned.\",\"pool\":\"Pool address.\"}},\"burnLiquiditySingle(address,uint256,bytes,uint256)\":{\"details\":\"The tokens are swapped automatically and the output is in a single token.\",\"params\":{\"data\":\"Data required by the pool to burn liquidity.\",\"liquidity\":\"Amount of liquidity tokens to burn.\",\"minWithdrawal\":\"Minimum amount of tokens to be returned.\",\"pool\":\"Pool address.\"}},\"complexPath(((address,address,bool,uint256,bytes)[],(address,address,uint64,bytes)[],(address,address,bool,uint256)[]))\":{\"details\":\"This function is not optimized for single swaps and should only be used in complex cases where the amounts are large enough that minimizing slippage by using multiple paths is worth the extra gas.\",\"params\":{\"params\":\"This includes everything needed for the swap. Look at the `ComplexPathParams` struct for more details.\"}},\"exactInput((address,uint256,uint256,(address,bytes)[]))\":{\"details\":\"Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.\",\"params\":{\"params\":\"This includes the addresses of the tokens, pools, amount of token A to swap, minimum amount of token B after the swap and data required by the pools for the swaps.\"}},\"exactInputLazy(uint256,(address,bytes)[])\":{\"details\":\"Ensure that the pools are trusted before calling this function. The pools can steal users' tokens. This function will unlikely be used in production but it shows how to use callbacks. One use case will be arbitrage.\",\"params\":{\"amountOutMinimum\":\"Minimum amount of token B after the swap.\",\"path\":\"Addresses of the pools and data required by the pools for the swaps.\"}},\"exactInputSingle((uint256,uint256,address,address,bytes))\":{\"details\":\"Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.\",\"params\":{\"params\":\"This includes the address of token A, pool, amount of token A to swap, minimum amount of token B after the swap and data required by the pool for the swap.\"}},\"exactInputSingleWithNativeToken((uint256,uint256,address,address,bytes))\":{\"details\":\"Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.\",\"params\":{\"params\":\"This includes the address of token A, pool, amount of token A to swap, minimum amount of token B after the swap and data required by the pool for the swap.\"}},\"exactInputWithNativeToken((address,uint256,uint256,(address,bytes)[]))\":{\"details\":\"Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.\",\"params\":{\"params\":\"This includes the addresses of the tokens, pools, amount of token A to swap, minimum amount of token B after the swap and data required by the pools for the swaps.\"}},\"permitThis(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"amount\":\"Token amount to grant spending right over.\",\"deadline\":\"Termination for signed approval (UTC timestamp in seconds).\",\"r\":\"Half of the ECDSA signature pair.\",\"s\":\"Half of the ECDSA signature pair.\",\"token\":\"Address of ERC-20 token.\",\"v\":\"The recovery byte of the signature.\"}},\"permitThisAllowed(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"expiry\":\"Termination for signed approval - UTC timestamp in seconds.\",\"nonce\":\"Token owner's nonce - increases at each call to {permit}.\",\"r\":\"Half of the ECDSA signature pair.\",\"s\":\"Half of the ECDSA signature pair.\",\"token\":\"Address of ERC-20 token.\",\"v\":\"The recovery byte of the signature.\"}}},\"stateVariables\":{\"cachedMsgSender\":{\"details\":\"Used to ensure that `tridentSwapCallback` is called only by the authorized address. These are set when someone calls a flash swap and reset afterwards.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addLiquidity((address,bool,uint256)[],address,uint256,bytes)\":{\"notice\":\"Add liquidity to a pool.\"},\"addLiquidityLazy(address,uint256,bytes)\":{\"notice\":\"Add liquidity to a pool using callbacks - same as `addLiquidity`, but now with callbacks.\"},\"approveMasterContract(uint8,bytes32,bytes32)\":{\"notice\":\"Helper function to allow batching of BentoBox master contract approvals so the first trade can happen in one transaction.\"},\"batch(bytes[])\":{\"notice\":\"Provides batch function calls for this contract and returns the data from all of them if they all succeed. Adapted from https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol, License-Identifier: GPL-2.0-or-later.\"},\"bento()\":{\"notice\":\"BentoBox token vault.\"},\"burnLiquidity(address,uint256,bytes,(address,uint256)[])\":{\"notice\":\"Burn liquidity tokens to get back `bento` tokens.\"},\"burnLiquiditySingle(address,uint256,bytes,uint256)\":{\"notice\":\"Burn liquidity tokens to get back `bento` tokens.\"},\"complexPath(((address,address,bool,uint256,bytes)[],(address,address,uint64,bytes)[],(address,address,bool,uint256)[]))\":{\"notice\":\"Swaps multiple input tokens to multiple output tokens using multiple paths, in different percentages. For example, you can swap 50 DAI + 100 USDC into 60% ETH and 40% BTC.\"},\"exactInput((address,uint256,uint256,(address,bytes)[]))\":{\"notice\":\"Swaps token A to token B indirectly by using multiple hops.\"},\"exactInputLazy(uint256,(address,bytes)[])\":{\"notice\":\"Swaps token A to token B by using callbacks.\"},\"exactInputSingle((uint256,uint256,address,address,bytes))\":{\"notice\":\"Swaps token A to token B directly. Swaps are done on `bento` tokens.\"},\"exactInputSingleWithNativeToken((uint256,uint256,address,address,bytes))\":{\"notice\":\"Swaps token A to token B directly. It's the same as `exactInputSingle` except it takes raw ERC-20 tokens from the users and deposits them into `bento`.\"},\"exactInputWithNativeToken((address,uint256,uint256,(address,bytes)[]))\":{\"notice\":\"Swaps token A to token B indirectly by using multiple hops. It's the same as `exactInput` except it takes raw ERC-20 tokens from the users and deposits them into `bento`.\"},\"masterDeployer()\":{\"notice\":\"Trident AMM master deployer contract.\"},\"permitThis(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Provides EIP-2612 signed approval for this contract to spend user tokens.\"},\"permitThisAllowed(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Provides DAI-derived signed approval for this contract to spend user tokens.\"},\"refundETH()\":{\"notice\":\"Recover mistakenly sent ETH.\"},\"sweepBentoBoxToken(address,uint256,address)\":{\"notice\":\"Recover mistakenly sent `bento` tokens.\"},\"sweepNativeToken(address,uint256,address)\":{\"notice\":\"Recover mistakenly sent ERC-20 tokens.\"},\"tridentMintCallback(bytes)\":{\"notice\":\"Can be used by the pool 'mint' functionality to take tokens from the user.\"},\"tridentSwapCallback(bytes)\":{\"notice\":\"Used by the pool 'flashSwap' functionality to take input tokens from the user.\"},\"unwrapWETH(uint256,address)\":{\"notice\":\"Unwrap this contract's `wETH` into ETH\"}},\"notice\":\"Router contract that helps in swapping across Trident pools.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TridentRouter.sol\":\"TridentRouter\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":99999},\"remappings\":[]},\"sources\":{\"contracts/TridentRouter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"./interfaces/IPool.sol\\\";\\nimport \\\"./interfaces/ITridentRouter.sol\\\";\\nimport \\\"./utils/RouterHelper.sol\\\";\\n\\n/// @notice Router contract that helps in swapping across Trident pools.\\ncontract TridentRouter is ITridentRouter, RouterHelper {\\n    /// @dev Used to ensure that `tridentSwapCallback` is called only by the authorized address.\\n    /// These are set when someone calls a flash swap and reset afterwards.\\n    address internal cachedMsgSender;\\n    address internal cachedPool;\\n\\n    mapping(address => bool) internal whitelistedPools;\\n\\n    constructor(\\n        IBentoBoxMinimal bento,\\n        IMasterDeployer masterDeployer,\\n        address wETH\\n    ) RouterHelper(bento, masterDeployer, wETH) {}\\n\\n    receive() external payable {\\n        require(msg.sender == wETH);\\n    }\\n\\n    /// @notice Swaps token A to token B directly. Swaps are done on `bento` tokens.\\n    /// @param params This includes the address of token A, pool, amount of token A to swap,\\n    /// minimum amount of token B after the swap and data required by the pool for the swap.\\n    /// @dev Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.\\n    function exactInputSingle(ExactInputSingleParams calldata params) public payable returns (uint256 amountOut) {\\n        // @dev Prefund the pool with token A.\\n        bento.transfer(params.tokenIn, msg.sender, params.pool, params.amountIn);\\n        // @dev Trigger the swap in the pool.\\n        amountOut = IPool(params.pool).swap(params.data);\\n        // @dev Ensure that the slippage wasn't too much. This assumes that the pool is honest.\\n        require(amountOut >= params.amountOutMinimum, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Swaps token A to token B indirectly by using multiple hops.\\n    /// @param params This includes the addresses of the tokens, pools, amount of token A to swap,\\n    /// minimum amount of token B after the swap and data required by the pools for the swaps.\\n    /// @dev Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.\\n    function exactInput(ExactInputParams calldata params) public payable returns (uint256 amountOut) {\\n        // @dev Pay the first pool directly.\\n        bento.transfer(params.tokenIn, msg.sender, params.path[0].pool, params.amountIn);\\n        // @dev Call every pool in the path.\\n        // Pool `N` should transfer its output tokens to pool `N+1` directly.\\n        // The last pool should transfer its output tokens to the user.\\n        // If the user wants to unwrap `wETH`, the final destination should be this contract and\\n        // a batch call should be made to `unwrapWETH`.\\n        for (uint256 i; i < params.path.length; i++) {\\n            // We don't necessarily need this check but saving users from themselves.\\n            isWhiteListed(params.path[i].pool);\\n            amountOut = IPool(params.path[i].pool).swap(params.path[i].data);\\n        }\\n        // @dev Ensure that the slippage wasn't too much. This assumes that the pool is honest.\\n        require(amountOut >= params.amountOutMinimum, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Swaps token A to token B by using callbacks.\\n    /// @param path Addresses of the pools and data required by the pools for the swaps.\\n    /// @param amountOutMinimum Minimum amount of token B after the swap.\\n    /// @dev Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.\\n    /// This function will unlikely be used in production but it shows how to use callbacks. One use case will be arbitrage.\\n    function exactInputLazy(uint256 amountOutMinimum, Path[] calldata path) public payable returns (uint256 amountOut) {\\n        // @dev Call every pool in the path.\\n        // Pool `N` should transfer its output tokens to pool `N+1` directly.\\n        // The last pool should transfer its output tokens to the user.\\n        for (uint256 i; i < path.length; i++) {\\n            isWhiteListed(path[i].pool);\\n            // @dev The cached `msg.sender` is used as the funder when the callback happens.\\n            cachedMsgSender = msg.sender;\\n            // @dev The cached pool must be the address that calls the callback.\\n            cachedPool = path[i].pool;\\n            amountOut = IPool(path[i].pool).flashSwap(path[i].data);\\n        }\\n        // @dev Resets the `cachedPool` to get a refund.\\n        // `1` is used as the default value to avoid the storage slot being released.\\n        cachedMsgSender = address(1);\\n        cachedPool = address(1);\\n        require(amountOut >= amountOutMinimum, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Swaps token A to token B directly. It's the same as `exactInputSingle` except\\n    /// it takes raw ERC-20 tokens from the users and deposits them into `bento`.\\n    /// @param params This includes the address of token A, pool, amount of token A to swap,\\n    /// minimum amount of token B after the swap and data required by the pool for the swap.\\n    /// @dev Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.\\n    function exactInputSingleWithNativeToken(ExactInputSingleParams calldata params) public payable returns (uint256 amountOut) {\\n        // @dev Deposits the native ERC-20 token from the user into the pool's `bento`.\\n        _depositToBentoBox(params.tokenIn, params.pool, params.amountIn);\\n        // @dev Trigger the swap in the pool.\\n        amountOut = IPool(params.pool).swap(params.data);\\n        // @dev Ensure that the slippage wasn't too much. This assumes that the pool is honest.\\n        require(amountOut >= params.amountOutMinimum, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Swaps token A to token B indirectly by using multiple hops. It's the same as `exactInput` except\\n    /// it takes raw ERC-20 tokens from the users and deposits them into `bento`.\\n    /// @param params This includes the addresses of the tokens, pools, amount of token A to swap,\\n    /// minimum amount of token B after the swap and data required by the pools for the swaps.\\n    /// @dev Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.\\n    function exactInputWithNativeToken(ExactInputParams calldata params) public payable returns (uint256 amountOut) {\\n        // @dev Deposits the native ERC-20 token from the user into the pool's `bento`.\\n        _depositToBentoBox(params.tokenIn, params.path[0].pool, params.amountIn);\\n        // @dev Call every pool in the path.\\n        // Pool `N` should transfer its output tokens to pool `N+1` directly.\\n        // The last pool should transfer its output tokens to the user.\\n        for (uint256 i; i < params.path.length; i++) {\\n            isWhiteListed(params.path[i].pool);\\n            amountOut = IPool(params.path[i].pool).swap(params.path[i].data);\\n        }\\n        // @dev Ensure that the slippage wasn't too much. This assumes that the pool is honest.\\n        require(amountOut >= params.amountOutMinimum, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Swaps multiple input tokens to multiple output tokens using multiple paths, in different percentages.\\n    /// For example, you can swap 50 DAI + 100 USDC into 60% ETH and 40% BTC.\\n    /// @param params This includes everything needed for the swap. Look at the `ComplexPathParams` struct for more details.\\n    /// @dev This function is not optimized for single swaps and should only be used in complex cases where\\n    /// the amounts are large enough that minimizing slippage by using multiple paths is worth the extra gas.\\n    function complexPath(ComplexPathParams calldata params) public payable {\\n        // @dev Deposit all initial tokens to respective pools and initiate the swaps.\\n        // Input tokens come from the user - output goes to following pools.\\n        for (uint256 i; i < params.initialPath.length; i++) {\\n            if (params.initialPath[i].native) {\\n                _depositToBentoBox(params.initialPath[i].tokenIn, params.initialPath[i].pool, params.initialPath[i].amount);\\n            } else {\\n                bento.transfer(params.initialPath[i].tokenIn, msg.sender, params.initialPath[i].pool, params.initialPath[i].amount);\\n            }\\n            isWhiteListed(params.initialPath[i].pool);\\n            IPool(params.initialPath[i].pool).swap(params.initialPath[i].data);\\n        }\\n        // @dev Do all the middle swaps. Input comes from previous pools - output goes to following pools.\\n        for (uint256 i; i < params.percentagePath.length; i++) {\\n            uint256 balanceShares = bento.balanceOf(params.percentagePath[i].tokenIn, address(this));\\n            uint256 transferShares = (balanceShares * params.percentagePath[i].balancePercentage) / uint256(10)**8;\\n            bento.transfer(params.percentagePath[i].tokenIn, address(this), params.percentagePath[i].pool, transferShares);\\n            isWhiteListed(params.percentagePath[i].pool);\\n            IPool(params.percentagePath[i].pool).swap(params.percentagePath[i].data);\\n        }\\n        // @dev Do all the final swaps. Input comes from previous pools - output goes to the user.\\n        for (uint256 i; i < params.output.length; i++) {\\n            uint256 balanceShares = bento.balanceOf(params.output[i].token, address(this));\\n            require(balanceShares >= params.output[i].minAmount, \\\"TOO_LITTLE_RECEIVED\\\");\\n            if (params.output[i].unwrapBento) {\\n                bento.withdraw(params.output[i].token, address(this), params.output[i].to, 0, balanceShares);\\n            } else {\\n                bento.transfer(params.output[i].token, address(this), params.output[i].to, balanceShares);\\n            }\\n        }\\n    }\\n\\n    /// @notice Add liquidity to a pool.\\n    /// @param tokenInput Token address and amount to add as liquidity.\\n    /// @param pool Pool address to add liquidity to.\\n    /// @param minLiquidity Minimum output liquidity - caps slippage.\\n    /// @param data Data required by the pool to add liquidity.\\n    function addLiquidity(\\n        TokenInput[] memory tokenInput,\\n        address pool,\\n        uint256 minLiquidity,\\n        bytes calldata data\\n    ) public payable returns (uint256 liquidity) {\\n        isWhiteListed(pool);\\n        // @dev Send all input tokens to the pool.\\n        for (uint256 i; i < tokenInput.length; i++) {\\n            if (tokenInput[i].native) {\\n                _depositToBentoBox(tokenInput[i].token, pool, tokenInput[i].amount);\\n            } else {\\n                bento.transfer(tokenInput[i].token, msg.sender, pool, tokenInput[i].amount);\\n            }\\n        }\\n        liquidity = IPool(pool).mint(data);\\n        require(liquidity >= minLiquidity, \\\"NOT_ENOUGH_LIQUIDITY_MINTED\\\");\\n    }\\n\\n    /// @notice Add liquidity to a pool using callbacks - same as `addLiquidity`, but now with callbacks.\\n    /// @dev The input tokens are sent to the pool during the callback.\\n    function addLiquidityLazy(\\n        address pool,\\n        uint256 minLiquidity,\\n        bytes calldata data\\n    ) public payable returns (uint256 liquidity) {\\n        isWhiteListed(pool);\\n        cachedMsgSender = msg.sender;\\n        cachedPool = pool;\\n        liquidity = IPool(pool).mint(data);\\n        cachedMsgSender = address(1);\\n        cachedPool = address(1);\\n        require(liquidity >= minLiquidity, \\\"NOT_ENOUGH_LIQUIDITY_MINTED\\\");\\n    }\\n\\n    /// @notice Burn liquidity tokens to get back `bento` tokens.\\n    /// @param pool Pool address.\\n    /// @param liquidity Amount of liquidity tokens to burn.\\n    /// @param data Data required by the pool to burn liquidity.\\n    /// @param minWithdrawals Minimum amount of `bento` tokens to be returned.\\n    function burnLiquidity(\\n        address pool,\\n        uint256 liquidity,\\n        bytes calldata data,\\n        IPool.TokenAmount[] memory minWithdrawals\\n    ) public {\\n        isWhiteListed(pool);\\n        safeTransferFrom(pool, msg.sender, pool, liquidity);\\n        IPool.TokenAmount[] memory withdrawnLiquidity = IPool(pool).burn(data);\\n        for (uint256 i; i < minWithdrawals.length; i++) {\\n            uint256 j;\\n            for (; j < withdrawnLiquidity.length; j++) {\\n                if (withdrawnLiquidity[j].token == minWithdrawals[i].token) {\\n                    require(withdrawnLiquidity[j].amount >= minWithdrawals[i].amount, \\\"TOO_LITTLE_RECEIVED\\\");\\n                    break;\\n                }\\n            }\\n            // @dev A token that is present in `minWithdrawals` is missing from `withdrawnLiquidity`.\\n            require(j < withdrawnLiquidity.length, \\\"INCORRECT_TOKEN_WITHDRAWN\\\");\\n        }\\n    }\\n\\n    /// @notice Burn liquidity tokens to get back `bento` tokens.\\n    /// @dev The tokens are swapped automatically and the output is in a single token.\\n    /// @param pool Pool address.\\n    /// @param liquidity Amount of liquidity tokens to burn.\\n    /// @param data Data required by the pool to burn liquidity.\\n    /// @param minWithdrawal Minimum amount of tokens to be returned.\\n    function burnLiquiditySingle(\\n        address pool,\\n        uint256 liquidity,\\n        bytes calldata data,\\n        uint256 minWithdrawal\\n    ) public {\\n        isWhiteListed(pool);\\n        // @dev Use 'liquidity = 0' for prefunding.\\n        safeTransferFrom(pool, msg.sender, pool, liquidity);\\n        uint256 withdrawn = IPool(pool).burnSingle(data);\\n        require(withdrawn >= minWithdrawal, \\\"TOO_LITTLE_RECEIVED\\\");\\n    }\\n\\n    /// @notice Used by the pool 'flashSwap' functionality to take input tokens from the user.\\n    function tridentSwapCallback(bytes calldata data) external {\\n        require(msg.sender == cachedPool, \\\"UNAUTHORIZED_CALLBACK\\\");\\n        TokenInput memory tokenInput = abi.decode(data, (TokenInput));\\n        // @dev Transfer the requested tokens to the pool.\\n        if (tokenInput.native) {\\n            _depositFromUserToBentoBox(tokenInput.token, cachedMsgSender, msg.sender, tokenInput.amount);\\n        } else {\\n            bento.transfer(tokenInput.token, cachedMsgSender, msg.sender, tokenInput.amount);\\n        }\\n        // @dev Resets the `msg.sender`'s authorization.\\n        cachedMsgSender = address(1);\\n    }\\n\\n    /// @notice Can be used by the pool 'mint' functionality to take tokens from the user.\\n    function tridentMintCallback(bytes calldata data) external {\\n        require(msg.sender == cachedPool, \\\"UNAUTHORIZED_CALLBACK\\\");\\n        TokenInput[] memory tokenInput = abi.decode(data, (TokenInput[]));\\n        // @dev Transfer the requested tokens to the pool.\\n        for (uint256 i; i < tokenInput.length; i++) {\\n            if (tokenInput[i].native) {\\n                _depositFromUserToBentoBox(tokenInput[i].token, cachedMsgSender, msg.sender, tokenInput[i].amount);\\n            } else {\\n                bento.transfer(tokenInput[i].token, cachedMsgSender, msg.sender, tokenInput[i].amount);\\n            }\\n        }\\n        // @dev Resets the `msg.sender`'s authorization.\\n        cachedMsgSender = address(1);\\n    }\\n\\n    /// @notice Recover mistakenly sent `bento` tokens.\\n    function sweepBentoBoxToken(\\n        address token,\\n        uint256 amount,\\n        address recipient\\n    ) external {\\n        bento.transfer(token, address(this), recipient, amount);\\n    }\\n\\n    /// @notice Recover mistakenly sent ERC-20 tokens.\\n    function sweepNativeToken(\\n        address token,\\n        uint256 amount,\\n        address recipient\\n    ) external {\\n        safeTransfer(token, recipient, amount);\\n    }\\n\\n    /// @notice Recover mistakenly sent ETH.\\n    function refundETH() external payable {\\n        if (address(this).balance != 0) safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @notice Unwrap this contract's `wETH` into ETH\\n    function unwrapWETH(uint256 amountMinimum, address recipient) external {\\n        uint256 balanceWETH = balanceOfThis(wETH);\\n        require(balanceWETH >= amountMinimum, \\\"INSUFFICIENT_WETH\\\");\\n        if (balanceWETH != 0) {\\n            withdrawFromWETH(balanceWETH);\\n            safeTransferETH(recipient, balanceWETH);\\n        }\\n    }\\n\\n    /// @notice Deposit from the user's wallet into BentoBox.\\n    /// @dev Amount is the native token amount. We let BentoBox do the conversion into shares.\\n    function _depositToBentoBox(\\n        address token,\\n        address recipient,\\n        uint256 amount\\n    ) internal {\\n        bento.deposit{value: token == USE_ETHEREUM ? amount : 0}(token, msg.sender, recipient, amount, 0);\\n    }\\n\\n    /// @notice Same effect as _depositToBentoBox() but with a sender parameter.\\n    function _depositFromUserToBentoBox(\\n        address token,\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) internal {\\n        bento.deposit{value: token == USE_ETHEREUM ? amount : 0}(token, sender, recipient, amount, 0);\\n    }\\n\\n    function isWhiteListed(address pool) internal {\\n        if (!whitelistedPools[pool]) {\\n            require(masterDeployer.pools(pool), \\\"INVALID POOL\\\");\\n            whitelistedPools[pool] = true;\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xf0fa741d0702a72762d9b01ad821b53d2d8a6d44673f94f1f53f93906622ea7a\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\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\",\"keccak256\":\"0x80ef2859d876a6b464e28dcaa03b4b0e8d1f81a946e3b3875d4fba66314dc369\",\"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/ITridentRouter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool router interface.\\ninterface ITridentRouter {\\n    struct Path {\\n        address pool;\\n        bytes data;\\n    }\\n\\n    struct ExactInputSingleParams {\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        address pool;\\n        address tokenIn;\\n        bytes data;\\n    }\\n\\n    struct ExactInputParams {\\n        address tokenIn;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        Path[] path;\\n    }\\n\\n    struct TokenInput {\\n        address token;\\n        bool native;\\n        uint256 amount;\\n    }\\n\\n    struct InitialPath {\\n        address tokenIn;\\n        address pool;\\n        bool native;\\n        uint256 amount;\\n        bytes data;\\n    }\\n\\n    struct PercentagePath {\\n        address tokenIn;\\n        address pool;\\n        uint64 balancePercentage; // Multiplied by 10^6. 100% = 100_000_000\\n        bytes data;\\n    }\\n\\n    struct Output {\\n        address token;\\n        address to;\\n        bool unwrapBento;\\n        uint256 minAmount;\\n    }\\n\\n    struct ComplexPathParams {\\n        InitialPath[] initialPath;\\n        PercentagePath[] percentagePath;\\n        Output[] output;\\n    }\\n}\\n\",\"keccak256\":\"0x40f1af6b213ff8827d515460f9057eb87ddc35d8020501f727d229ea239cbf24\",\"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/utils/RouterHelper.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../interfaces/IBentoBoxMinimal.sol\\\";\\nimport \\\"../interfaces/IMasterDeployer.sol\\\";\\nimport \\\"../TridentRouter.sol\\\";\\nimport \\\"./TridentPermit.sol\\\";\\n\\n/// @notice Trident router helper contract.\\ncontract RouterHelper is TridentPermit {\\n    /// @notice BentoBox token vault.\\n    IBentoBoxMinimal public immutable bento;\\n    /// @notice Trident AMM master deployer contract.\\n    IMasterDeployer public immutable masterDeployer;\\n    /// @notice ERC-20 token for wrapped ETH (v9).\\n    address internal immutable wETH;\\n    /// @notice The user should use 0x0 if they want to deposit ETH\\n    address constant USE_ETHEREUM = address(0);\\n\\n    constructor(\\n        IBentoBoxMinimal _bento,\\n        IMasterDeployer _masterDeployer,\\n        address _wETH\\n    ) {\\n        bento = _bento;\\n        masterDeployer = _masterDeployer;\\n        wETH = _wETH;\\n        _bento.registerProtocol();\\n    }\\n\\n    /// @notice Provides batch function calls for this contract and returns the data from all of them if they all succeed.\\n    /// Adapted from https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol, License-Identifier: GPL-2.0-or-later.\\n    /// @dev The `msg.value` should not be trusted for any method callable from this function.\\n    /// @dev Uses a modified version of the batch function - preventing multiple calls of the single input swap functions\\n    /// @param data ABI-encoded params for each of the calls to make to this contract.\\n    /// @return results The results from each of the calls passed in via `data`.\\n    function batch(bytes[] calldata data) external payable returns (bytes[] memory results) {\\n        results = new bytes[](data.length);\\n        // We only allow one exactInputSingle call to be made in a single batch call.\\n        // This is not really needed but we want to save users from signing malicious payloads.\\n        // We also don't want nested batch calls.\\n        bool swapCalled;\\n        for (uint256 i = 0; i < data.length; i++) {\\n            bytes4 selector = getSelector(data[i]);\\n            if (selector == TridentRouter.exactInputSingle.selector || selector == TridentRouter.exactInputSingleWithNativeToken.selector) {\\n                require(!swapCalled, \\\"Swap called twice\\\");\\n                swapCalled = true;\\n            } else {\\n                require(selector != this.batch.selector, \\\"Nested Batch\\\");\\n            }\\n\\n            (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n            if (!success) {\\n                // Next 5 lines from https://ethereum.stackexchange.com/a/83577.\\n                if (result.length < 68) revert();\\n                assembly {\\n                    result := add(result, 0x04)\\n                }\\n                revert(abi.decode(result, (string)));\\n            }\\n            results[i] = result;\\n        }\\n    }\\n\\n    function deployPool(address factory, bytes calldata deployData) external payable returns (address) {\\n        return masterDeployer.deployPool(factory, deployData);\\n    }\\n\\n    /// @notice Helper function to allow batching of BentoBox master contract approvals so the first trade can happen in one transaction.\\n    function approveMasterContract(\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable {\\n        bento.setMasterContractApproval(msg.sender, address(this), true, v, r, s);\\n    }\\n\\n    /// @notice Provides gas-optimized balance check on this contract to avoid redundant extcodesize check in addition to returndatasize check.\\n    /// @param token Address of ERC-20 token.\\n    /// @return balance Token amount held by this contract.\\n    function balanceOfThis(address token) internal view returns (uint256 balance) {\\n        (bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(0x70a08231, address(this))); // @dev balanceOf(address).\\n        require(success && data.length >= 32, \\\"BALANCE_OF_FAILED\\\");\\n        balance = abi.decode(data, (uint256));\\n    }\\n\\n    /// @notice Provides 'safe' ERC-20 {transfer} for tokens that don't consistently return true/false.\\n    /// @param token Address of ERC-20 token.\\n    /// @param recipient Account to send tokens to.\\n    /// @param amount Token amount to send.\\n    function safeTransfer(\\n        address token,\\n        address recipient,\\n        uint256 amount\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, recipient, amount)); // @dev transfer(address,uint256).\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"TRANSFER_FAILED\\\");\\n    }\\n\\n    /// @notice Provides 'safe' ERC-20 {transferFrom} for tokens that don't consistently return true/false.\\n    /// @param token Address of ERC-20 token.\\n    /// @param sender Account to send tokens from.\\n    /// @param recipient Account to send tokens to.\\n    /// @param amount Token amount to send.\\n    function safeTransferFrom(\\n        address token,\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, sender, recipient, amount)); // @dev transferFrom(address,address,uint256).\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), \\\"TRANSFER_FROM_FAILED\\\");\\n    }\\n\\n    /// @notice Provides low-level `wETH` {withdraw}.\\n    /// @param amount Token amount to unwrap into ETH.\\n    function withdrawFromWETH(uint256 amount) internal {\\n        (bool success, ) = wETH.call(abi.encodeWithSelector(0x2e1a7d4d, amount)); // @dev withdraw(uint256).\\n        require(success, \\\"WITHDRAW_FROM_WETH_FAILED\\\");\\n    }\\n\\n    /// @notice Provides 'safe' ETH transfer.\\n    /// @param recipient Account to send ETH to.\\n    /// @param amount ETH amount to send.\\n    function safeTransferETH(address recipient, uint256 amount) internal {\\n        (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n        require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n    }\\n\\n    /**\\n     * @notice function to extract the selector of a bytes calldata\\n     * @param _data the calldata bytes\\n     */\\n    function getSelector(bytes memory _data) internal pure returns (bytes4 sig) {\\n        assembly {\\n            sig := mload(add(_data, 32))\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x6ba7ef30206daf568f31c0c315f2da991f5425ba76aa97ec3faf5c80af4e6592\",\"license\":\"GPL-3.0-or-later\"},\"contracts/utils/TridentPermit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Generic contract exposing the permit functionality.\\nabstract contract TridentPermit {\\n    error PermitFailed();\\n\\n    /// @notice Provides EIP-2612 signed approval for this contract to spend user tokens.\\n    /// @param token Address of ERC-20 token.\\n    /// @param amount Token amount to grant spending right over.\\n    /// @param deadline Termination for signed approval (UTC timestamp in seconds).\\n    /// @param v The recovery byte of the signature.\\n    /// @param r Half of the ECDSA signature pair.\\n    /// @param s Half of the ECDSA signature pair.\\n    function permitThis(\\n        address token,\\n        uint256 amount,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external {\\n        (bool success, ) = token.call(abi.encodeWithSelector(0xd505accf, msg.sender, address(this), amount, deadline, v, r, s)); // permit(address,address,uint256,uint256,uint8,bytes32,bytes32).\\n        if (!success) revert PermitFailed();\\n    }\\n\\n    /// @notice Provides DAI-derived signed approval for this contract to spend user tokens.\\n    /// @param token Address of ERC-20 token.\\n    /// @param nonce Token owner's nonce - increases at each call to {permit}.\\n    /// @param expiry Termination for signed approval - UTC timestamp in seconds.\\n    /// @param v The recovery byte of the signature.\\n    /// @param r Half of the ECDSA signature pair.\\n    /// @param s Half of the ECDSA signature pair.\\n    function permitThisAllowed(\\n        address token,\\n        uint256 nonce,\\n        uint256 expiry,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external {\\n        (bool success, ) = token.call(abi.encodeWithSelector(0x8fcbaf0c, msg.sender, address(this), nonce, expiry, true, v, r, s)); // permit(address,address,uint256,uint256,bool,uint8,bytes32,bytes32).\\n        if (!success) revert PermitFailed();\\n    }\\n}\\n\",\"keccak256\":\"0x41a005fbeccd614c4d0027c168c7fb6ba7689504356ff9040c50d2a3c53d0ec6\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}",
  "bytecode": "0x60e06040523480156200001157600080fd5b5060405162004b4d38038062004b4d8339810160408190526200003491620000c4565b6001600160601b0319606084811b821660805283811b821660a05282901b1660c0526040805163577268d960e11b815290518491849184916001600160a01b0385169163aee4d1b29160048082019260009290919082900301818387803b1580156200009f57600080fd5b505af1158015620000b4573d6000803e3d6000fd5b5050505050505050505062000131565b600080600060608486031215620000da57600080fd5b8351620000e78162000118565b6020850151909350620000fa8162000118565b60408501519092506200010d8162000118565b809150509250925092565b6001600160a01b03811681146200012e57600080fd5b50565b60805160601c60a05160601c60c05160601c61495e620001ef600039600081816101a101528181612e6501526137d80152600081816104360152818161104a015261308e0152600081816102e9015281816106da015281816110f6015281816113c60152818161164201528181611ae001528181611e650152818161214e015281816122d90152818161259501528181612772015281816128d901528181612b4301528181612cff01528181612f250152613582015261495e6000f3fe6080604052600436106101845760003560e01c806377631981116100d6578063a9b62c231161007f578063ced10b4911610059578063ced10b4914610404578063cf58879a14610424578063e16d9ce51461045857600080fd5b8063a9b62c23146103b1578063b96c5c0e146103d1578063bd50c7b1146103e457600080fd5b806394ae4ab2116100b057806394ae4ab21461036b57806398a691de1461038b5780639fa744911461039e57600080fd5b8063776319811461030b578063783312d91461032b5780639128efda1461034b57600080fd5b80631e897afb116101385780632cfcb94f116101125780632cfcb94f146102b1578063403335a8146102c45780634da31827146102d757600080fd5b80631e897afb14610246578063250558dc146102665780632c0d9a011461029e57600080fd5b806312210e8a1161016957806312210e8a1461020b5780631aa349a8146102135780631ab5d6c81461023357600080fd5b80630b0d1b1e146101d25780630f93d439146101f857600080fd5b366101cd573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101cb57600080fd5b005b600080fd5b6101e56101e03660046140c0565b610478565b6040519081526020015b60405180910390f35b6101e56102063660046140fb565b6106c1565b6101cb6108cd565b34801561021f57600080fd5b506101cb61022e366004613ce1565b6108df565b6101e561024136600461419b565b610a11565b610259610254366004613d9f565b610c7d565b6040516101ef919061434a565b610279610274366004613adf565b61100a565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ef565b6101e56102ac3660046140c0565b6110dd565b6101e56102bf366004613eda565b611340565b6101cb6102d2366004614228565b6115f0565b3480156102e357600080fd5b506102797f000000000000000000000000000000000000000000000000000000000000000081565b34801561031757600080fd5b506101cb610326366004613d45565b6116b9565b34801561033757600080fd5b506101cb610346366004613bd2565b6117e6565b34801561035757600080fd5b506101cb610366366004613b34565b611a86565b34801561037757600080fd5b506101cb610386366004613b34565b611b0f565b6101e5610399366004613b76565b611b1f565b6101e56103ac3660046140fb565b611ca8565b3480156103bd57600080fd5b506101cb6103cc366004613d45565b611ce4565b6101cb6103df366004614085565b611d42565b3480156103f057600080fd5b506101cb6103ff366004613f9d565b612a14565b34801561041057600080fd5b506101cb61041f366004613f9d565b612bd2565b34801561043057600080fd5b506102797f000000000000000000000000000000000000000000000000000000000000000081565b34801561046457600080fd5b506101cb61047336600461416b565b612e5e565b60006104d261048a6020840184613aa5565b61049760608501856143f1565b60008181106104a8576104a861489a565b90506020028101906104ba919061455a565b6104c8906020810190613aa5565b8460200135612f0e565b60005b6104e260608401846143f1565b9050811015610648576105306104fb60608501856143f1565b8381811061050b5761050b61489a565b905060200281019061051d919061455a565b61052b906020810190613aa5565b61301c565b61053d60608401846143f1565b8281811061054d5761054d61489a565b905060200281019061055f919061455a565b61056d906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61059560608601866143f1565b848181106105a5576105a561489a565b90506020028101906105b7919061455a565b6105c59060208101906144c1565b6040518363ffffffff1660e01b81526004016105e29291906143ca565b602060405180830381600087803b1580156105fc57600080fd5b505af1158015610610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106349190614152565b91508061064081614832565b9150506104d5565b5081604001358110156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064015b60405180910390fd5b919050565b600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61070f6080850160608601613aa5565b336107206060870160408801613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015284356064820152608401600060405180830381600087803b15801561079d57600080fd5b505af11580156107b1573d6000803e3d6000fd5b506107c6925050506060830160408401613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a6107ee60808501856144c1565b6040518363ffffffff1660e01b815260040161080b9291906143ca565b602060405180830381600087803b15801561082557600080fd5b505af1158015610839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085d9190614152565b905081602001358110156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b47156108dd576108dd33476131c0565b565b6108e88561301c565b6108f48533878761328a565b6040517faf8c09bf00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff87169063af8c09bf9061094b90879087906004016143ca565b602060405180830381600087803b15801561096557600080fd5b505af1158015610979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099d9190614152565b905081811015610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b505050505050565b6000805b82811015610bd557610a3284848381811061050b5761050b61489a565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055838382818110610a6e57610a6e61489a565b9050602002810190610a80919061455a565b610a8e906020810190613aa5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055838382818110610ae557610ae561489a565b9050602002810190610af7919061455a565b610b05906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663053da1c8858584818110610b3257610b3261489a565b9050602002810190610b44919061455a565b610b529060208101906144c1565b6040518363ffffffff1660e01b8152600401610b6f9291906143ca565b602060405180830381600087803b158015610b8957600080fd5b505af1158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc19190614152565b915080610bcd81614832565b915050610a15565b506000805460017fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092558154168117905583811015610c76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b9392505050565b60608167ffffffffffffffff811115610c9857610c986148c9565b604051908082528060200260200182016040528015610ccb57816020015b6060815260200190600190039081610cb65790505b5090506000805b83811015611002576000610d3d868684818110610cf157610cf161489a565b9050602002810190610d0391906144c1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133fb92505050565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f0f93d439000000000000000000000000000000000000000000000000000000001480610dd057507fffffffff0000000000000000000000000000000000000000000000000000000081167f9fa7449100000000000000000000000000000000000000000000000000000000145b15610e46578215610e3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f537761702063616c6c656420747769636500000000000000000000000000000060448201526064016106b3565b60019250610ef2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f1e897afb000000000000000000000000000000000000000000000000000000001415610ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4e6573746564204261746368000000000000000000000000000000000000000060448201526064016106b3565b60008030888886818110610f0857610f0861489a565b9050602002810190610f1a91906144c1565b604051610f289291906142ee565b600060405180830381855af49150503d8060008114610f63576040519150601f19603f3d011682016040523d82523d6000602084013e610f68565b606091505b509150915081610fce57604481511015610f8157600080fd5b60048101905080806020019051810190610f9b9190613fd3565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b391906143de565b80868581518110610fe157610fe161489a565b60200260200101819052505050508080610ffa90614832565b915050610cd2565b505092915050565b6040517f250558dc00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063250558dc906110839087908790879060040161431a565b602060405180830381600087803b15801561109d57600080fd5b505af11580156110b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190613ac2565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc6111286020850185613aa5565b3361113660608701876143f1565b60008181106111475761114761489a565b9050602002810190611159919061455a565b611167906020810190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260208501356064820152608401600060405180830381600087803b1580156111e757600080fd5b505af11580156111fb573d6000803e3d6000fd5b5050505060005b61120f60608401846143f1565b9050811015610648576112286104fb60608501856143f1565b61123560608401846143f1565b828181106112455761124561489a565b9050602002810190611257919061455a565b611265906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61128d60608601866143f1565b8481811061129d5761129d61489a565b90506020028101906112af919061455a565b6112bd9060208101906144c1565b6040518363ffffffff1660e01b81526004016112da9291906143ca565b602060405180830381600087803b1580156112f457600080fd5b505af1158015611308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132c9190614152565b91508061133881614832565b915050611202565b600061134b8561301c565b60005b86518110156114d4578681815181106113695761136961489a565b602002602001015160200151156113c4576113bf87828151811061138f5761138f61489a565b602002602001015160000151878984815181106113ae576113ae61489a565b602002602001015160400151612f0e565b6114c2565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc8883815181106114125761141261489a565b60200260200101516000015133898b86815181106114325761143261489a565b6020026020010151604001516040518563ffffffff1660e01b815260040161148f949392919073ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b600060405180830381600087803b1580156114a957600080fd5b505af11580156114bd573d6000803e3d6000fd5b505050505b806114cc81614832565b91505061134e565b506040517f7ba0e2e700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861690637ba0e2e79061152990869086906004016143ca565b602060405180830381600087803b15801561154357600080fd5b505af1158015611557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157b9190614152565b9050838110156115e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e4f545f454e4f5547485f4c49515549444954595f4d494e544544000000000060448201526064016106b3565b95945050505050565b6040517fc0a47c930000000000000000000000000000000000000000000000000000000081523360048201523060248201526001604482015260ff841660648201526084810183905260a481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063c0a47c939060c4015b600060405180830381600087803b15801561169c57600080fd5b505af11580156116b0573d6000803e3d6000fd5b50505050505050565b6040513360248201523060448201526064810186905260848101859052600160a482015260ff841660c482015260e48101839052610104810182905260009073ffffffffffffffffffffffffffffffffffffffff881690638fcbaf0c90610124015b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161176991906142fe565b6000604051808303816000865af19150503d80600081146117a6576040519150601f19603f3d011682016040523d82523d6000602084013e6117ab565b606091505b50509050806116b0576040517fb78cb0dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ef8561301c565b6117fb8533878761328a565b6040517f2a07b6c700000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff871690632a07b6c79061185290879087906004016143ca565b600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526118c69190810190613de1565b905060005b82518110156116b05760005b8251811015611a09578382815181106118f2576118f261489a565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff168382815181106119265761192661489a565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1614156119f7578382815181106119605761196061489a565b60200260200101516020015183828151811061197e5761197e61489a565b60200260200101516020015110156119f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b611a09565b80611a0181614832565b9150506118d7565b82518110611a73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f494e434f52524543545f544f4b454e5f57495448445241574e0000000000000060448201526064016106b3565b5080611a7e81614832565b9150506118cb565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301528281166044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401611682565b611b1a838284613402565b505050565b6000611b2a8561301c565b600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811633179091556001805473ffffffffffffffffffffffffffffffffffffffff88169216821790556040517f7ba0e2e7000000000000000000000000000000000000000000000000000000008152637ba0e2e790611bb490869086906004016143ca565b602060405180830381600087803b158015611bce57600080fd5b505af1158015611be2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c069190614152565b6000805460017fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117909255815416811790559050838110156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e4f545f454e4f5547485f4c49515549444954595f4d494e544544000000000060448201526064016106b3565b6000611cd4611cbd6080840160608501613aa5565b611ccd6060850160408601613aa5565b8435612f0e565b6107c66060830160408401613aa5565b604051336024820152306044820152606481018690526084810185905260ff841660a482015260c4810183905260e4810182905260009073ffffffffffffffffffffffffffffffffffffffff88169063d505accf906101040161171b565b60005b611d4f82806143f1565b905081101561211b57611d6282806143f1565b82818110611d7257611d7261489a565b9050602002810190611d849190614526565b611d95906060810190604001613f63565b15611e4e57611e49611da783806143f1565b83818110611db757611db761489a565b9050602002810190611dc99190614526565b611dd7906020810190613aa5565b611de184806143f1565b84818110611df157611df161489a565b9050602002810190611e039190614526565b611e14906040810190602001613aa5565b611e1e85806143f1565b85818110611e2e57611e2e61489a565b9050602002810190611e409190614526565b60600135612f0e565b611fc7565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc611e9484806143f1565b84818110611ea457611ea461489a565b9050602002810190611eb69190614526565b611ec4906020810190613aa5565b33611ecf86806143f1565b86818110611edf57611edf61489a565b9050602002810190611ef19190614526565b611f02906040810190602001613aa5565b611f0c87806143f1565b87818110611f1c57611f1c61489a565b9050602002810190611f2e9190614526565b60405160e086901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff94851660048201529284166024840152921660448201526060909101356064820152608401600060405180830381600087803b158015611fae57600080fd5b505af1158015611fc2573d6000803e3d6000fd5b505050505b612007611fd483806143f1565b83818110611fe457611fe461489a565b9050602002810190611ff69190614526565b61052b906040810190602001613aa5565b61201182806143f1565b828181106120215761202161489a565b90506020028101906120339190614526565b612044906040810190602001613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61206984806143f1565b848181106120795761207961489a565b905060200281019061208b9190614526565b6120999060808101906144c1565b6040518363ffffffff1660e01b81526004016120b69291906143ca565b602060405180830381600087803b1580156120d057600080fd5b505af11580156120e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121089190614152565b508061211381614832565b915050611d45565b5060005b61212c60208301836143f1565b905081101561256257600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f7888aec61218060208601866143f1565b858181106121905761219061489a565b90506020028101906121a2919061458e565b6121b0906020810190613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015230602482015260440160206040518083038186803b15801561221a57600080fd5b505afa15801561222e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122529190614152565b905060006122626008600a6146fa565b61226f60208601866143f1565b8581811061227f5761227f61489a565b9050602002810190612291919061458e565b6122a29060608101906040016141fe565b6122b69067ffffffffffffffff16846147c5565b6122c0919061465e565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61230b60208701876143f1565b8681811061231b5761231b61489a565b905060200281019061232d919061458e565b61233b906020810190613aa5565b3061234960208901896143f1565b888181106123595761235961489a565b905060200281019061236b919061458e565b61237c906040810190602001613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260648101849052608401600060405180830381600087803b1580156123f957600080fd5b505af115801561240d573d6000803e3d6000fd5b50612445925061242391505060208601866143f1565b858181106124335761243361489a565b9050602002810190611ff6919061458e565b61245260208501856143f1565b848181106124625761246261489a565b9050602002810190612474919061458e565b612485906040810190602001613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a6124ad60208701876143f1565b868181106124bd576124bd61489a565b90506020028101906124cf919061458e565b6124dd9060608101906144c1565b6040518363ffffffff1660e01b81526004016124fa9291906143ca565b602060405180830381600087803b15801561251457600080fd5b505af1158015612528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254c9190614152565b505050808061255a90614832565b91505061211f565b5060005b6125736040830183614459565b9050811015612a1057600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f7888aec6125c76040860186614459565b858181106125d7576125d761489a565b6125ed9260206080909202019081019150613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015230602482015260440160206040518083038186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190614152565b905061269e6040840184614459565b838181106126ae576126ae61489a565b90506080020160600135811015612721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b61272e6040840184614459565b8381811061273e5761273e61489a565b90506080020160400160208101906127569190613f63565b156128c25773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166397da6d306127a46040860186614459565b858181106127b4576127b461489a565b6127ca9260206080909202019081019150613aa5565b306127d86040880188614459565b878181106127e8576127e861489a565b90506080020160200160208101906128009190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff938416600482015291831660248301529091166044820152600060648201526084810184905260a4016040805180830381600087803b15801561288357600080fd5b505af1158015612897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bb91906141da565b50506129fd565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61290b6040860186614459565b8581811061291b5761291b61489a565b6129319260206080909202019081019150613aa5565b3061293f6040880188614459565b8781811061294f5761294f61489a565b90506080020160200160208101906129679190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260648101849052608401600060405180830381600087803b1580156129e457600080fd5b505af11580156129f8573d6000803e3d6000fd5b505050505b5080612a0881614832565b915050612566565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f43414c4c4241434b000000000000000000000060448201526064016106b3565b6000612aa382840184614136565b9050806020015115612ae15780516000546040830151612adc929173ffffffffffffffffffffffffffffffffffffffff1690339061356b565b612ba2565b805160005460408084015190517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015233604483015260648201527f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b158015612b8957600080fd5b505af1158015612b9d573d6000803e3d6000fd5b505050505b5050600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016600117905550565b60015473ffffffffffffffffffffffffffffffffffffffff163314612c53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f43414c4c4241434b000000000000000000000060448201526064016106b3565b6000612c6182840184613ea5565b905060005b8151811015612e2d57818181518110612c8157612c8161489a565b60200260200101516020015115612cfd57612cf8828281518110612ca757612ca761489a565b60200260200101516000015160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633858581518110612ce757612ce761489a565b60200260200101516040015161356b565b612e1b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc838381518110612d4b57612d4b61489a565b60200260200101516000015160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633868681518110612d8b57612d8b61489a565b6020026020010151604001516040518563ffffffff1660e01b8152600401612de8949392919073ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b600060405180830381600087803b158015612e0257600080fd5b505af1158015612e16573d6000803e3d6000fd5b505050505b80612e2581614832565b915050612c66565b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790555050565b6000612e897f0000000000000000000000000000000000000000000000000000000000000000613674565b905082811015612ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e53554646494349454e545f5745544800000000000000000000000000000060448201526064016106b3565b8015611b1a57612f04816137d4565b611b1a82826131c0565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116906302b9446c90851615612f5b576000612f5d565b825b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff808816600483015233602483015286166044820152606481018590526000608482015260a40160408051808303818588803b158015612fdc57600080fd5b505af1158015612ff0573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061301591906141da565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604090205460ff166131bd576040517fa4063dbc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a4063dbc9060240160206040518083038186803b1580156130d057600080fd5b505afa1580156130e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131089190613f80565b61316e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f494e56414c494420504f4f4c000000000000000000000000000000000000000060448201526064016106b3565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461321a576040519150601f19603f3d011682016040523d82523d6000602084013e61321f565b606091505b5050905080611b1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016106b3565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161332991906142fe565b6000604051808303816000865af19150503d8060008114613366576040519150601f19603f3d011682016040523d82523d6000602084013e61336b565b606091505b50915091508180156133955750805115806133955750808060200190518101906133959190613f80565b610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016106b3565b6020015190565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052915160009283929087169161349991906142fe565b6000604051808303816000865af19150503d80600081146134d6576040519150601f19603f3d011682016040523d82523d6000602084013e6134db565b606091505b50915091508180156135055750805115806135055750808060200190518101906135059190613f80565b613015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016106b3565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116906302b9446c908616156135b85760006135ba565b825b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff8089166004830152808816602483015286166044820152606481018590526000608482015260a40160408051808303818588803b15801561363b57600080fd5b505af115801561364f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a0991906141da565b604080513060248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a082310000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169161370691906142fe565b600060405180830381855afa9150503d8060008114613741576040519150601f19603f3d011682016040523d82523d6000602084013e613746565b606091505b509150915081801561375a57506020815110155b6137c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42414c414e43455f4f465f4641494c454400000000000000000000000000000060448201526064016106b3565b808060200190518101906110d59190614152565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d8360405160240161382591815260200190565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161387391906142fe565b6000604051808303816000865af19150503d80600081146138b0576040519150601f19603f3d011682016040523d82523d6000602084013e6138b5565b606091505b5050905080612a10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f57495448445241575f46524f4d5f574554485f4641494c45440000000000000060448201526064016106b3565b60008083601f84011261393257600080fd5b50813567ffffffffffffffff81111561394a57600080fd5b6020830191508360208260051b850101111561396557600080fd5b9250929050565b600082601f83011261397d57600080fd5b8135602061399261398d8361463a565b6145eb565b828152818101908583016060808602880185018910156139b157600080fd5b60005b868110156139d8576139c68a84613a28565b855293850193918101916001016139b4565b509198975050505050505050565b60008083601f8401126139f857600080fd5b50813567ffffffffffffffff811115613a1057600080fd5b60208301915083602082850101111561396557600080fd5b600060608284031215613a3a57600080fd5b6040516060810181811067ffffffffffffffff82111715613a5d57613a5d6148c9565b6040529050808235613a6e816148f8565b81526020830135613a7e8161491a565b6020820152604092830135920191909152919050565b803560ff811681146106bc57600080fd5b600060208284031215613ab757600080fd5b8135610c76816148f8565b600060208284031215613ad457600080fd5b8151610c76816148f8565b600080600060408486031215613af457600080fd5b8335613aff816148f8565b9250602084013567ffffffffffffffff811115613b1b57600080fd5b613b27868287016139e6565b9497909650939450505050565b600080600060608486031215613b4957600080fd5b8335613b54816148f8565b9250602084013591506040840135613b6b816148f8565b809150509250925092565b60008060008060608587031215613b8c57600080fd5b8435613b97816148f8565b935060208501359250604085013567ffffffffffffffff811115613bba57600080fd5b613bc6878288016139e6565b95989497509550505050565b600080600080600060808688031215613bea57600080fd5b8535613bf5816148f8565b9450602086810135945060408088013567ffffffffffffffff80821115613c1b57600080fd5b613c278b838c016139e6565b909750955060608a0135915080821115613c4057600080fd5b508801601f81018a13613c5257600080fd5b8035613c6061398d8261463a565b8082825285820191508584018d878560061b8701011115613c8057600080fd5b600094505b83851015613ccd5785818f031215613c9c57600080fd5b613ca46145c2565b8135613caf816148f8565b81528188013588820152835260019490940193918601918501613c85565b508096505050505050509295509295909350565b600080600080600060808688031215613cf957600080fd5b8535613d04816148f8565b945060208601359350604086013567ffffffffffffffff811115613d2757600080fd5b613d33888289016139e6565b96999598509660600135949350505050565b60008060008060008060c08789031215613d5e57600080fd5b8635613d69816148f8565b95506020870135945060408701359350613d8560608801613a94565b92506080870135915060a087013590509295509295509295565b60008060208385031215613db257600080fd5b823567ffffffffffffffff811115613dc957600080fd5b613dd585828601613920565b90969095509350505050565b60006020808385031215613df457600080fd5b825167ffffffffffffffff811115613e0b57600080fd5b8301601f81018513613e1c57600080fd5b8051613e2a61398d8261463a565b80828252848201915084840188868560061b8701011115613e4a57600080fd5b60009450845b84811015613e9757604080838c031215613e68578687fd5b613e706145c2565b8351613e7b816148f8565b8152838901518982015285529387019390910190600101613e50565b509098975050505050505050565b600060208284031215613eb757600080fd5b813567ffffffffffffffff811115613ece57600080fd5b6110d58482850161396c565b600080600080600060808688031215613ef257600080fd5b853567ffffffffffffffff80821115613f0a57600080fd5b613f1689838a0161396c565b965060208801359150613f28826148f8565b9094506040870135935060608701359080821115613f4557600080fd5b50613f52888289016139e6565b969995985093965092949392505050565b600060208284031215613f7557600080fd5b8135610c768161491a565b600060208284031215613f9257600080fd5b8151610c768161491a565b60008060208385031215613fb057600080fd5b823567ffffffffffffffff811115613fc757600080fd5b613dd5858286016139e6565b600060208284031215613fe557600080fd5b815167ffffffffffffffff80821115613ffd57600080fd5b818401915084601f83011261401157600080fd5b815181811115614023576140236148c9565b61405460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016145eb565b915080825285602082850101111561406b57600080fd5b61407c816020840160208601614802565b50949350505050565b60006020828403121561409757600080fd5b813567ffffffffffffffff8111156140ae57600080fd5b820160608185031215610c7657600080fd5b6000602082840312156140d257600080fd5b813567ffffffffffffffff8111156140e957600080fd5b820160808185031215610c7657600080fd5b60006020828403121561410d57600080fd5b813567ffffffffffffffff81111561412457600080fd5b820160a08185031215610c7657600080fd5b60006060828403121561414857600080fd5b610c768383613a28565b60006020828403121561416457600080fd5b5051919050565b6000806040838503121561417e57600080fd5b823591506020830135614190816148f8565b809150509250929050565b6000806000604084860312156141b057600080fd5b83359250602084013567ffffffffffffffff8111156141ce57600080fd5b613b2786828701613920565b600080604083850312156141ed57600080fd5b505080516020909101519092909150565b60006020828403121561421057600080fd5b813567ffffffffffffffff81168114610c7657600080fd5b60008060006060848603121561423d57600080fd5b61424684613a94565b95602085013595506040909401359392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600081518084526142bc816020860160208601614802565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8183823760009101908152919050565b60008251614310818460208701614802565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006115e760408301848661425b565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156143bd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143ab8583516142a4565b94509285019290850190600101614371565b5092979650505050505050565b6020815260006110d560208301848661425b565b602081526000610c7660208301846142a4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261442657600080fd5b83018035915067ffffffffffffffff82111561444157600080fd5b6020019150600581901b360382131561396557600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261448e57600080fd5b83018035915067ffffffffffffffff8211156144a957600080fd5b6020019150600781901b360382131561396557600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144f657600080fd5b83018035915067ffffffffffffffff82111561451157600080fd5b60200191503681900382131561396557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261431057600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261431057600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261431057600080fd5b6040805190810167ffffffffffffffff811182821017156145e5576145e56148c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614632576146326148c9565b604052919050565b600067ffffffffffffffff821115614654576146546148c9565b5060051b60200190565b600082614694577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b808511156146f257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156146d8576146d861486b565b808516156146e557918102915b93841c939080029061469e565b509250929050565b6000610c7660ff841683600082614713575060016147bf565b81614720575060006147bf565b816001811461473657600281146147405761475c565b60019150506147bf565b60ff8411156147515761475161486b565b50506001821b6147bf565b5060208310610133831016604e8410600b841016171561477f575081810a6147bf565b6147898383614699565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156147bb576147bb61486b565b0290505b92915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147fd576147fd61486b565b500290565b60005b8381101561481d578181015183820152602001614805565b8381111561482c576000848401525b50505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148645761486461486b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146131bd57600080fd5b80151581146131bd57600080fdfea2646970667358221220546643013aa9960ddc9a104ff1a15209cf74c452eaccc696f0dbc48212c0eb0d64736f6c63430008070033",
  "deployedBytecode": "0x6080604052600436106101845760003560e01c806377631981116100d6578063a9b62c231161007f578063ced10b4911610059578063ced10b4914610404578063cf58879a14610424578063e16d9ce51461045857600080fd5b8063a9b62c23146103b1578063b96c5c0e146103d1578063bd50c7b1146103e457600080fd5b806394ae4ab2116100b057806394ae4ab21461036b57806398a691de1461038b5780639fa744911461039e57600080fd5b8063776319811461030b578063783312d91461032b5780639128efda1461034b57600080fd5b80631e897afb116101385780632cfcb94f116101125780632cfcb94f146102b1578063403335a8146102c45780634da31827146102d757600080fd5b80631e897afb14610246578063250558dc146102665780632c0d9a011461029e57600080fd5b806312210e8a1161016957806312210e8a1461020b5780631aa349a8146102135780631ab5d6c81461023357600080fd5b80630b0d1b1e146101d25780630f93d439146101f857600080fd5b366101cd573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101cb57600080fd5b005b600080fd5b6101e56101e03660046140c0565b610478565b6040519081526020015b60405180910390f35b6101e56102063660046140fb565b6106c1565b6101cb6108cd565b34801561021f57600080fd5b506101cb61022e366004613ce1565b6108df565b6101e561024136600461419b565b610a11565b610259610254366004613d9f565b610c7d565b6040516101ef919061434a565b610279610274366004613adf565b61100a565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ef565b6101e56102ac3660046140c0565b6110dd565b6101e56102bf366004613eda565b611340565b6101cb6102d2366004614228565b6115f0565b3480156102e357600080fd5b506102797f000000000000000000000000000000000000000000000000000000000000000081565b34801561031757600080fd5b506101cb610326366004613d45565b6116b9565b34801561033757600080fd5b506101cb610346366004613bd2565b6117e6565b34801561035757600080fd5b506101cb610366366004613b34565b611a86565b34801561037757600080fd5b506101cb610386366004613b34565b611b0f565b6101e5610399366004613b76565b611b1f565b6101e56103ac3660046140fb565b611ca8565b3480156103bd57600080fd5b506101cb6103cc366004613d45565b611ce4565b6101cb6103df366004614085565b611d42565b3480156103f057600080fd5b506101cb6103ff366004613f9d565b612a14565b34801561041057600080fd5b506101cb61041f366004613f9d565b612bd2565b34801561043057600080fd5b506102797f000000000000000000000000000000000000000000000000000000000000000081565b34801561046457600080fd5b506101cb61047336600461416b565b612e5e565b60006104d261048a6020840184613aa5565b61049760608501856143f1565b60008181106104a8576104a861489a565b90506020028101906104ba919061455a565b6104c8906020810190613aa5565b8460200135612f0e565b60005b6104e260608401846143f1565b9050811015610648576105306104fb60608501856143f1565b8381811061050b5761050b61489a565b905060200281019061051d919061455a565b61052b906020810190613aa5565b61301c565b61053d60608401846143f1565b8281811061054d5761054d61489a565b905060200281019061055f919061455a565b61056d906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61059560608601866143f1565b848181106105a5576105a561489a565b90506020028101906105b7919061455a565b6105c59060208101906144c1565b6040518363ffffffff1660e01b81526004016105e29291906143ca565b602060405180830381600087803b1580156105fc57600080fd5b505af1158015610610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106349190614152565b91508061064081614832565b9150506104d5565b5081604001358110156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064015b60405180910390fd5b919050565b600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61070f6080850160608601613aa5565b336107206060870160408801613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015284356064820152608401600060405180830381600087803b15801561079d57600080fd5b505af11580156107b1573d6000803e3d6000fd5b506107c6925050506060830160408401613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a6107ee60808501856144c1565b6040518363ffffffff1660e01b815260040161080b9291906143ca565b602060405180830381600087803b15801561082557600080fd5b505af1158015610839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085d9190614152565b905081602001358110156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b47156108dd576108dd33476131c0565b565b6108e88561301c565b6108f48533878761328a565b6040517faf8c09bf00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff87169063af8c09bf9061094b90879087906004016143ca565b602060405180830381600087803b15801561096557600080fd5b505af1158015610979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099d9190614152565b905081811015610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b505050505050565b6000805b82811015610bd557610a3284848381811061050b5761050b61489a565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055838382818110610a6e57610a6e61489a565b9050602002810190610a80919061455a565b610a8e906020810190613aa5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055838382818110610ae557610ae561489a565b9050602002810190610af7919061455a565b610b05906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663053da1c8858584818110610b3257610b3261489a565b9050602002810190610b44919061455a565b610b529060208101906144c1565b6040518363ffffffff1660e01b8152600401610b6f9291906143ca565b602060405180830381600087803b158015610b8957600080fd5b505af1158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc19190614152565b915080610bcd81614832565b915050610a15565b506000805460017fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092558154168117905583811015610c76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b9392505050565b60608167ffffffffffffffff811115610c9857610c986148c9565b604051908082528060200260200182016040528015610ccb57816020015b6060815260200190600190039081610cb65790505b5090506000805b83811015611002576000610d3d868684818110610cf157610cf161489a565b9050602002810190610d0391906144c1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133fb92505050565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f0f93d439000000000000000000000000000000000000000000000000000000001480610dd057507fffffffff0000000000000000000000000000000000000000000000000000000081167f9fa7449100000000000000000000000000000000000000000000000000000000145b15610e46578215610e3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f537761702063616c6c656420747769636500000000000000000000000000000060448201526064016106b3565b60019250610ef2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f1e897afb000000000000000000000000000000000000000000000000000000001415610ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4e6573746564204261746368000000000000000000000000000000000000000060448201526064016106b3565b60008030888886818110610f0857610f0861489a565b9050602002810190610f1a91906144c1565b604051610f289291906142ee565b600060405180830381855af49150503d8060008114610f63576040519150601f19603f3d011682016040523d82523d6000602084013e610f68565b606091505b509150915081610fce57604481511015610f8157600080fd5b60048101905080806020019051810190610f9b9190613fd3565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b391906143de565b80868581518110610fe157610fe161489a565b60200260200101819052505050508080610ffa90614832565b915050610cd2565b505092915050565b6040517f250558dc00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063250558dc906110839087908790879060040161431a565b602060405180830381600087803b15801561109d57600080fd5b505af11580156110b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190613ac2565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc6111286020850185613aa5565b3361113660608701876143f1565b60008181106111475761114761489a565b9050602002810190611159919061455a565b611167906020810190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260208501356064820152608401600060405180830381600087803b1580156111e757600080fd5b505af11580156111fb573d6000803e3d6000fd5b5050505060005b61120f60608401846143f1565b9050811015610648576112286104fb60608501856143f1565b61123560608401846143f1565b828181106112455761124561489a565b9050602002810190611257919061455a565b611265906020810190613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61128d60608601866143f1565b8481811061129d5761129d61489a565b90506020028101906112af919061455a565b6112bd9060208101906144c1565b6040518363ffffffff1660e01b81526004016112da9291906143ca565b602060405180830381600087803b1580156112f457600080fd5b505af1158015611308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132c9190614152565b91508061133881614832565b915050611202565b600061134b8561301c565b60005b86518110156114d4578681815181106113695761136961489a565b602002602001015160200151156113c4576113bf87828151811061138f5761138f61489a565b602002602001015160000151878984815181106113ae576113ae61489a565b602002602001015160400151612f0e565b6114c2565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc8883815181106114125761141261489a565b60200260200101516000015133898b86815181106114325761143261489a565b6020026020010151604001516040518563ffffffff1660e01b815260040161148f949392919073ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b600060405180830381600087803b1580156114a957600080fd5b505af11580156114bd573d6000803e3d6000fd5b505050505b806114cc81614832565b91505061134e565b506040517f7ba0e2e700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861690637ba0e2e79061152990869086906004016143ca565b602060405180830381600087803b15801561154357600080fd5b505af1158015611557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157b9190614152565b9050838110156115e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e4f545f454e4f5547485f4c49515549444954595f4d494e544544000000000060448201526064016106b3565b95945050505050565b6040517fc0a47c930000000000000000000000000000000000000000000000000000000081523360048201523060248201526001604482015260ff841660648201526084810183905260a481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063c0a47c939060c4015b600060405180830381600087803b15801561169c57600080fd5b505af11580156116b0573d6000803e3d6000fd5b50505050505050565b6040513360248201523060448201526064810186905260848101859052600160a482015260ff841660c482015260e48101839052610104810182905260009073ffffffffffffffffffffffffffffffffffffffff881690638fcbaf0c90610124015b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161176991906142fe565b6000604051808303816000865af19150503d80600081146117a6576040519150601f19603f3d011682016040523d82523d6000602084013e6117ab565b606091505b50509050806116b0576040517fb78cb0dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ef8561301c565b6117fb8533878761328a565b6040517f2a07b6c700000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff871690632a07b6c79061185290879087906004016143ca565b600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526118c69190810190613de1565b905060005b82518110156116b05760005b8251811015611a09578382815181106118f2576118f261489a565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff168382815181106119265761192661489a565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1614156119f7578382815181106119605761196061489a565b60200260200101516020015183828151811061197e5761197e61489a565b60200260200101516020015110156119f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b611a09565b80611a0181614832565b9150506118d7565b82518110611a73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f494e434f52524543545f544f4b454e5f57495448445241574e0000000000000060448201526064016106b3565b5080611a7e81614832565b9150506118cb565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301523060248301528281166044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401611682565b611b1a838284613402565b505050565b6000611b2a8561301c565b600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811633179091556001805473ffffffffffffffffffffffffffffffffffffffff88169216821790556040517f7ba0e2e7000000000000000000000000000000000000000000000000000000008152637ba0e2e790611bb490869086906004016143ca565b602060405180830381600087803b158015611bce57600080fd5b505af1158015611be2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c069190614152565b6000805460017fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117909255815416811790559050838110156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e4f545f454e4f5547485f4c49515549444954595f4d494e544544000000000060448201526064016106b3565b6000611cd4611cbd6080840160608501613aa5565b611ccd6060850160408601613aa5565b8435612f0e565b6107c66060830160408401613aa5565b604051336024820152306044820152606481018690526084810185905260ff841660a482015260c4810183905260e4810182905260009073ffffffffffffffffffffffffffffffffffffffff88169063d505accf906101040161171b565b60005b611d4f82806143f1565b905081101561211b57611d6282806143f1565b82818110611d7257611d7261489a565b9050602002810190611d849190614526565b611d95906060810190604001613f63565b15611e4e57611e49611da783806143f1565b83818110611db757611db761489a565b9050602002810190611dc99190614526565b611dd7906020810190613aa5565b611de184806143f1565b84818110611df157611df161489a565b9050602002810190611e039190614526565b611e14906040810190602001613aa5565b611e1e85806143f1565b85818110611e2e57611e2e61489a565b9050602002810190611e409190614526565b60600135612f0e565b611fc7565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc611e9484806143f1565b84818110611ea457611ea461489a565b9050602002810190611eb69190614526565b611ec4906020810190613aa5565b33611ecf86806143f1565b86818110611edf57611edf61489a565b9050602002810190611ef19190614526565b611f02906040810190602001613aa5565b611f0c87806143f1565b87818110611f1c57611f1c61489a565b9050602002810190611f2e9190614526565b60405160e086901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff94851660048201529284166024840152921660448201526060909101356064820152608401600060405180830381600087803b158015611fae57600080fd5b505af1158015611fc2573d6000803e3d6000fd5b505050505b612007611fd483806143f1565b83818110611fe457611fe461489a565b9050602002810190611ff69190614526565b61052b906040810190602001613aa5565b61201182806143f1565b828181106120215761202161489a565b90506020028101906120339190614526565b612044906040810190602001613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a61206984806143f1565b848181106120795761207961489a565b905060200281019061208b9190614526565b6120999060808101906144c1565b6040518363ffffffff1660e01b81526004016120b69291906143ca565b602060405180830381600087803b1580156120d057600080fd5b505af11580156120e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121089190614152565b508061211381614832565b915050611d45565b5060005b61212c60208301836143f1565b905081101561256257600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f7888aec61218060208601866143f1565b858181106121905761219061489a565b90506020028101906121a2919061458e565b6121b0906020810190613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015230602482015260440160206040518083038186803b15801561221a57600080fd5b505afa15801561222e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122529190614152565b905060006122626008600a6146fa565b61226f60208601866143f1565b8581811061227f5761227f61489a565b9050602002810190612291919061458e565b6122a29060608101906040016141fe565b6122b69067ffffffffffffffff16846147c5565b6122c0919061465e565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61230b60208701876143f1565b8681811061231b5761231b61489a565b905060200281019061232d919061458e565b61233b906020810190613aa5565b3061234960208901896143f1565b888181106123595761235961489a565b905060200281019061236b919061458e565b61237c906040810190602001613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260648101849052608401600060405180830381600087803b1580156123f957600080fd5b505af115801561240d573d6000803e3d6000fd5b50612445925061242391505060208601866143f1565b858181106124335761243361489a565b9050602002810190611ff6919061458e565b61245260208501856143f1565b848181106124625761246261489a565b9050602002810190612474919061458e565b612485906040810190602001613aa5565b73ffffffffffffffffffffffffffffffffffffffff1663627dd56a6124ad60208701876143f1565b868181106124bd576124bd61489a565b90506020028101906124cf919061458e565b6124dd9060608101906144c1565b6040518363ffffffff1660e01b81526004016124fa9291906143ca565b602060405180830381600087803b15801561251457600080fd5b505af1158015612528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254c9190614152565b505050808061255a90614832565b91505061211f565b5060005b6125736040830183614459565b9050811015612a1057600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f7888aec6125c76040860186614459565b858181106125d7576125d761489a565b6125ed9260206080909202019081019150613aa5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015230602482015260440160206040518083038186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190614152565b905061269e6040840184614459565b838181106126ae576126ae61489a565b90506080020160600135811015612721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f544f4f5f4c4954544c455f52454345495645440000000000000000000000000060448201526064016106b3565b61272e6040840184614459565b8381811061273e5761273e61489a565b90506080020160400160208101906127569190613f63565b156128c25773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166397da6d306127a46040860186614459565b858181106127b4576127b461489a565b6127ca9260206080909202019081019150613aa5565b306127d86040880188614459565b878181106127e8576127e861489a565b90506080020160200160208101906128009190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff938416600482015291831660248301529091166044820152600060648201526084810184905260a4016040805180830381600087803b15801561288357600080fd5b505af1158015612897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bb91906141da565b50506129fd565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f18d03cc61290b6040860186614459565b8581811061291b5761291b61489a565b6129319260206080909202019081019150613aa5565b3061293f6040880188614459565b8781811061294f5761294f61489a565b90506080020160200160208101906129679190613aa5565b60405160e085901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152909116604482015260648101849052608401600060405180830381600087803b1580156129e457600080fd5b505af11580156129f8573d6000803e3d6000fd5b505050505b5080612a0881614832565b915050612566565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f43414c4c4241434b000000000000000000000060448201526064016106b3565b6000612aa382840184614136565b9050806020015115612ae15780516000546040830151612adc929173ffffffffffffffffffffffffffffffffffffffff1690339061356b565b612ba2565b805160005460408084015190517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015233604483015260648201527f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b158015612b8957600080fd5b505af1158015612b9d573d6000803e3d6000fd5b505050505b5050600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016600117905550565b60015473ffffffffffffffffffffffffffffffffffffffff163314612c53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f43414c4c4241434b000000000000000000000060448201526064016106b3565b6000612c6182840184613ea5565b905060005b8151811015612e2d57818181518110612c8157612c8161489a565b60200260200101516020015115612cfd57612cf8828281518110612ca757612ca761489a565b60200260200101516000015160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633858581518110612ce757612ce761489a565b60200260200101516040015161356b565b612e1b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc838381518110612d4b57612d4b61489a565b60200260200101516000015160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633868681518110612d8b57612d8b61489a565b6020026020010151604001516040518563ffffffff1660e01b8152600401612de8949392919073ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b600060405180830381600087803b158015612e0257600080fd5b505af1158015612e16573d6000803e3d6000fd5b505050505b80612e2581614832565b915050612c66565b5050600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790555050565b6000612e897f0000000000000000000000000000000000000000000000000000000000000000613674565b905082811015612ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e53554646494349454e545f5745544800000000000000000000000000000060448201526064016106b3565b8015611b1a57612f04816137d4565b611b1a82826131c0565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116906302b9446c90851615612f5b576000612f5d565b825b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff808816600483015233602483015286166044820152606481018590526000608482015260a40160408051808303818588803b158015612fdc57600080fd5b505af1158015612ff0573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061301591906141da565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604090205460ff166131bd576040517fa4063dbc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a4063dbc9060240160206040518083038186803b1580156130d057600080fd5b505afa1580156130e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131089190613f80565b61316e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f494e56414c494420504f4f4c000000000000000000000000000000000000000060448201526064016106b3565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461321a576040519150601f19603f3d011682016040523d82523d6000602084013e61321f565b606091505b5050905080611b1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016106b3565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161332991906142fe565b6000604051808303816000865af19150503d8060008114613366576040519150601f19603f3d011682016040523d82523d6000602084013e61336b565b606091505b50915091508180156133955750805115806133955750808060200190518101906133959190613f80565b610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016106b3565b6020015190565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052915160009283929087169161349991906142fe565b6000604051808303816000865af19150503d80600081146134d6576040519150601f19603f3d011682016040523d82523d6000602084013e6134db565b606091505b50915091508180156135055750805115806135055750808060200190518101906135059190613f80565b613015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016106b3565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116906302b9446c908616156135b85760006135ba565b825b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff8089166004830152808816602483015286166044820152606481018590526000608482015260a40160408051808303818588803b15801561363b57600080fd5b505af115801561364f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a0991906141da565b604080513060248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a082310000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169161370691906142fe565b600060405180830381855afa9150503d8060008114613741576040519150601f19603f3d011682016040523d82523d6000602084013e613746565b606091505b509150915081801561375a57506020815110155b6137c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f42414c414e43455f4f465f4641494c454400000000000000000000000000000060448201526064016106b3565b808060200190518101906110d59190614152565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d8360405160240161382591815260200190565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161387391906142fe565b6000604051808303816000865af19150503d80600081146138b0576040519150601f19603f3d011682016040523d82523d6000602084013e6138b5565b606091505b5050905080612a10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f57495448445241575f46524f4d5f574554485f4641494c45440000000000000060448201526064016106b3565b60008083601f84011261393257600080fd5b50813567ffffffffffffffff81111561394a57600080fd5b6020830191508360208260051b850101111561396557600080fd5b9250929050565b600082601f83011261397d57600080fd5b8135602061399261398d8361463a565b6145eb565b828152818101908583016060808602880185018910156139b157600080fd5b60005b868110156139d8576139c68a84613a28565b855293850193918101916001016139b4565b509198975050505050505050565b60008083601f8401126139f857600080fd5b50813567ffffffffffffffff811115613a1057600080fd5b60208301915083602082850101111561396557600080fd5b600060608284031215613a3a57600080fd5b6040516060810181811067ffffffffffffffff82111715613a5d57613a5d6148c9565b6040529050808235613a6e816148f8565b81526020830135613a7e8161491a565b6020820152604092830135920191909152919050565b803560ff811681146106bc57600080fd5b600060208284031215613ab757600080fd5b8135610c76816148f8565b600060208284031215613ad457600080fd5b8151610c76816148f8565b600080600060408486031215613af457600080fd5b8335613aff816148f8565b9250602084013567ffffffffffffffff811115613b1b57600080fd5b613b27868287016139e6565b9497909650939450505050565b600080600060608486031215613b4957600080fd5b8335613b54816148f8565b9250602084013591506040840135613b6b816148f8565b809150509250925092565b60008060008060608587031215613b8c57600080fd5b8435613b97816148f8565b935060208501359250604085013567ffffffffffffffff811115613bba57600080fd5b613bc6878288016139e6565b95989497509550505050565b600080600080600060808688031215613bea57600080fd5b8535613bf5816148f8565b9450602086810135945060408088013567ffffffffffffffff80821115613c1b57600080fd5b613c278b838c016139e6565b909750955060608a0135915080821115613c4057600080fd5b508801601f81018a13613c5257600080fd5b8035613c6061398d8261463a565b8082825285820191508584018d878560061b8701011115613c8057600080fd5b600094505b83851015613ccd5785818f031215613c9c57600080fd5b613ca46145c2565b8135613caf816148f8565b81528188013588820152835260019490940193918601918501613c85565b508096505050505050509295509295909350565b600080600080600060808688031215613cf957600080fd5b8535613d04816148f8565b945060208601359350604086013567ffffffffffffffff811115613d2757600080fd5b613d33888289016139e6565b96999598509660600135949350505050565b60008060008060008060c08789031215613d5e57600080fd5b8635613d69816148f8565b95506020870135945060408701359350613d8560608801613a94565b92506080870135915060a087013590509295509295509295565b60008060208385031215613db257600080fd5b823567ffffffffffffffff811115613dc957600080fd5b613dd585828601613920565b90969095509350505050565b60006020808385031215613df457600080fd5b825167ffffffffffffffff811115613e0b57600080fd5b8301601f81018513613e1c57600080fd5b8051613e2a61398d8261463a565b80828252848201915084840188868560061b8701011115613e4a57600080fd5b60009450845b84811015613e9757604080838c031215613e68578687fd5b613e706145c2565b8351613e7b816148f8565b8152838901518982015285529387019390910190600101613e50565b509098975050505050505050565b600060208284031215613eb757600080fd5b813567ffffffffffffffff811115613ece57600080fd5b6110d58482850161396c565b600080600080600060808688031215613ef257600080fd5b853567ffffffffffffffff80821115613f0a57600080fd5b613f1689838a0161396c565b965060208801359150613f28826148f8565b9094506040870135935060608701359080821115613f4557600080fd5b50613f52888289016139e6565b969995985093965092949392505050565b600060208284031215613f7557600080fd5b8135610c768161491a565b600060208284031215613f9257600080fd5b8151610c768161491a565b60008060208385031215613fb057600080fd5b823567ffffffffffffffff811115613fc757600080fd5b613dd5858286016139e6565b600060208284031215613fe557600080fd5b815167ffffffffffffffff80821115613ffd57600080fd5b818401915084601f83011261401157600080fd5b815181811115614023576140236148c9565b61405460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016145eb565b915080825285602082850101111561406b57600080fd5b61407c816020840160208601614802565b50949350505050565b60006020828403121561409757600080fd5b813567ffffffffffffffff8111156140ae57600080fd5b820160608185031215610c7657600080fd5b6000602082840312156140d257600080fd5b813567ffffffffffffffff8111156140e957600080fd5b820160808185031215610c7657600080fd5b60006020828403121561410d57600080fd5b813567ffffffffffffffff81111561412457600080fd5b820160a08185031215610c7657600080fd5b60006060828403121561414857600080fd5b610c768383613a28565b60006020828403121561416457600080fd5b5051919050565b6000806040838503121561417e57600080fd5b823591506020830135614190816148f8565b809150509250929050565b6000806000604084860312156141b057600080fd5b83359250602084013567ffffffffffffffff8111156141ce57600080fd5b613b2786828701613920565b600080604083850312156141ed57600080fd5b505080516020909101519092909150565b60006020828403121561421057600080fd5b813567ffffffffffffffff81168114610c7657600080fd5b60008060006060848603121561423d57600080fd5b61424684613a94565b95602085013595506040909401359392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600081518084526142bc816020860160208601614802565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8183823760009101908152919050565b60008251614310818460208701614802565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006115e760408301848661425b565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156143bd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143ab8583516142a4565b94509285019290850190600101614371565b5092979650505050505050565b6020815260006110d560208301848661425b565b602081526000610c7660208301846142a4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261442657600080fd5b83018035915067ffffffffffffffff82111561444157600080fd5b6020019150600581901b360382131561396557600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261448e57600080fd5b83018035915067ffffffffffffffff8211156144a957600080fd5b6020019150600781901b360382131561396557600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126144f657600080fd5b83018035915067ffffffffffffffff82111561451157600080fd5b60200191503681900382131561396557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261431057600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261431057600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261431057600080fd5b6040805190810167ffffffffffffffff811182821017156145e5576145e56148c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614632576146326148c9565b604052919050565b600067ffffffffffffffff821115614654576146546148c9565b5060051b60200190565b600082614694577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b808511156146f257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156146d8576146d861486b565b808516156146e557918102915b93841c939080029061469e565b509250929050565b6000610c7660ff841683600082614713575060016147bf565b81614720575060006147bf565b816001811461473657600281146147405761475c565b60019150506147bf565b60ff8411156147515761475161486b565b50506001821b6147bf565b5060208310610133831016604e8410600b841016171561477f575081810a6147bf565b6147898383614699565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156147bb576147bb61486b565b0290505b92915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147fd576147fd61486b565b500290565b60005b8381101561481d578181015183820152602001614805565b8381111561482c576000848401525b50505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148645761486461486b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146131bd57600080fd5b80151581146131bd57600080fdfea2646970667358221220546643013aa9960ddc9a104ff1a15209cf74c452eaccc696f0dbc48212c0eb0d64736f6c63430008070033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "addLiquidity((address,bool,uint256)[],address,uint256,bytes)": {
        "params": {
          "data": "Data required by the pool to add liquidity.",
          "minLiquidity": "Minimum output liquidity - caps slippage.",
          "pool": "Pool address to add liquidity to.",
          "tokenInput": "Token address and amount to add as liquidity."
        }
      },
      "addLiquidityLazy(address,uint256,bytes)": {
        "details": "The input tokens are sent to the pool during the callback."
      },
      "batch(bytes[])": {
        "details": "The `msg.value` should not be trusted for any method callable from this function.Uses a modified version of the batch function - preventing multiple calls of the single input swap functions",
        "params": {
          "data": "ABI-encoded params for each of the calls to make to this contract."
        },
        "returns": {
          "results": "The results from each of the calls passed in via `data`."
        }
      },
      "burnLiquidity(address,uint256,bytes,(address,uint256)[])": {
        "params": {
          "data": "Data required by the pool to burn liquidity.",
          "liquidity": "Amount of liquidity tokens to burn.",
          "minWithdrawals": "Minimum amount of `bento` tokens to be returned.",
          "pool": "Pool address."
        }
      },
      "burnLiquiditySingle(address,uint256,bytes,uint256)": {
        "details": "The tokens are swapped automatically and the output is in a single token.",
        "params": {
          "data": "Data required by the pool to burn liquidity.",
          "liquidity": "Amount of liquidity tokens to burn.",
          "minWithdrawal": "Minimum amount of tokens to be returned.",
          "pool": "Pool address."
        }
      },
      "complexPath(((address,address,bool,uint256,bytes)[],(address,address,uint64,bytes)[],(address,address,bool,uint256)[]))": {
        "details": "This function is not optimized for single swaps and should only be used in complex cases where the amounts are large enough that minimizing slippage by using multiple paths is worth the extra gas.",
        "params": {
          "params": "This includes everything needed for the swap. Look at the `ComplexPathParams` struct for more details."
        }
      },
      "exactInput((address,uint256,uint256,(address,bytes)[]))": {
        "details": "Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.",
        "params": {
          "params": "This includes the addresses of the tokens, pools, amount of token A to swap, minimum amount of token B after the swap and data required by the pools for the swaps."
        }
      },
      "exactInputLazy(uint256,(address,bytes)[])": {
        "details": "Ensure that the pools are trusted before calling this function. The pools can steal users' tokens. This function will unlikely be used in production but it shows how to use callbacks. One use case will be arbitrage.",
        "params": {
          "amountOutMinimum": "Minimum amount of token B after the swap.",
          "path": "Addresses of the pools and data required by the pools for the swaps."
        }
      },
      "exactInputSingle((uint256,uint256,address,address,bytes))": {
        "details": "Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.",
        "params": {
          "params": "This includes the address of token A, pool, amount of token A to swap, minimum amount of token B after the swap and data required by the pool for the swap."
        }
      },
      "exactInputSingleWithNativeToken((uint256,uint256,address,address,bytes))": {
        "details": "Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.",
        "params": {
          "params": "This includes the address of token A, pool, amount of token A to swap, minimum amount of token B after the swap and data required by the pool for the swap."
        }
      },
      "exactInputWithNativeToken((address,uint256,uint256,(address,bytes)[]))": {
        "details": "Ensure that the pools are trusted before calling this function. The pools can steal users' tokens.",
        "params": {
          "params": "This includes the addresses of the tokens, pools, amount of token A to swap, minimum amount of token B after the swap and data required by the pools for the swaps."
        }
      },
      "permitThis(address,uint256,uint256,uint8,bytes32,bytes32)": {
        "params": {
          "amount": "Token amount to grant spending right over.",
          "deadline": "Termination for signed approval (UTC timestamp in seconds).",
          "r": "Half of the ECDSA signature pair.",
          "s": "Half of the ECDSA signature pair.",
          "token": "Address of ERC-20 token.",
          "v": "The recovery byte of the signature."
        }
      },
      "permitThisAllowed(address,uint256,uint256,uint8,bytes32,bytes32)": {
        "params": {
          "expiry": "Termination for signed approval - UTC timestamp in seconds.",
          "nonce": "Token owner's nonce - increases at each call to {permit}.",
          "r": "Half of the ECDSA signature pair.",
          "s": "Half of the ECDSA signature pair.",
          "token": "Address of ERC-20 token.",
          "v": "The recovery byte of the signature."
        }
      }
    },
    "stateVariables": {
      "cachedMsgSender": {
        "details": "Used to ensure that `tridentSwapCallback` is called only by the authorized address. These are set when someone calls a flash swap and reset afterwards."
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "addLiquidity((address,bool,uint256)[],address,uint256,bytes)": {
        "notice": "Add liquidity to a pool."
      },
      "addLiquidityLazy(address,uint256,bytes)": {
        "notice": "Add liquidity to a pool using callbacks - same as `addLiquidity`, but now with callbacks."
      },
      "approveMasterContract(uint8,bytes32,bytes32)": {
        "notice": "Helper function to allow batching of BentoBox master contract approvals so the first trade can happen in one transaction."
      },
      "batch(bytes[])": {
        "notice": "Provides batch function calls for this contract and returns the data from all of them if they all succeed. Adapted from https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol, License-Identifier: GPL-2.0-or-later."
      },
      "bento()": {
        "notice": "BentoBox token vault."
      },
      "burnLiquidity(address,uint256,bytes,(address,uint256)[])": {
        "notice": "Burn liquidity tokens to get back `bento` tokens."
      },
      "burnLiquiditySingle(address,uint256,bytes,uint256)": {
        "notice": "Burn liquidity tokens to get back `bento` tokens."
      },
      "complexPath(((address,address,bool,uint256,bytes)[],(address,address,uint64,bytes)[],(address,address,bool,uint256)[]))": {
        "notice": "Swaps multiple input tokens to multiple output tokens using multiple paths, in different percentages. For example, you can swap 50 DAI + 100 USDC into 60% ETH and 40% BTC."
      },
      "exactInput((address,uint256,uint256,(address,bytes)[]))": {
        "notice": "Swaps token A to token B indirectly by using multiple hops."
      },
      "exactInputLazy(uint256,(address,bytes)[])": {
        "notice": "Swaps token A to token B by using callbacks."
      },
      "exactInputSingle((uint256,uint256,address,address,bytes))": {
        "notice": "Swaps token A to token B directly. Swaps are done on `bento` tokens."
      },
      "exactInputSingleWithNativeToken((uint256,uint256,address,address,bytes))": {
        "notice": "Swaps token A to token B directly. It's the same as `exactInputSingle` except it takes raw ERC-20 tokens from the users and deposits them into `bento`."
      },
      "exactInputWithNativeToken((address,uint256,uint256,(address,bytes)[]))": {
        "notice": "Swaps token A to token B indirectly by using multiple hops. It's the same as `exactInput` except it takes raw ERC-20 tokens from the users and deposits them into `bento`."
      },
      "masterDeployer()": {
        "notice": "Trident AMM master deployer contract."
      },
      "permitThis(address,uint256,uint256,uint8,bytes32,bytes32)": {
        "notice": "Provides EIP-2612 signed approval for this contract to spend user tokens."
      },
      "permitThisAllowed(address,uint256,uint256,uint8,bytes32,bytes32)": {
        "notice": "Provides DAI-derived signed approval for this contract to spend user tokens."
      },
      "refundETH()": {
        "notice": "Recover mistakenly sent ETH."
      },
      "sweepBentoBoxToken(address,uint256,address)": {
        "notice": "Recover mistakenly sent `bento` tokens."
      },
      "sweepNativeToken(address,uint256,address)": {
        "notice": "Recover mistakenly sent ERC-20 tokens."
      },
      "tridentMintCallback(bytes)": {
        "notice": "Can be used by the pool 'mint' functionality to take tokens from the user."
      },
      "tridentSwapCallback(bytes)": {
        "notice": "Used by the pool 'flashSwap' functionality to take input tokens from the user."
      },
      "unwrapWETH(uint256,address)": {
        "notice": "Unwrap this contract's `wETH` into ETH"
      }
    },
    "notice": "Router contract that helps in swapping across Trident pools.",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 683,
        "contract": "contracts/TridentRouter.sol:TridentRouter",
        "label": "cachedMsgSender",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 685,
        "contract": "contracts/TridentRouter.sol:TridentRouter",
        "label": "cachedPool",
        "offset": 0,
        "slot": "1",
        "type": "t_address"
      },
      {
        "astId": 689,
        "contract": "contracts/TridentRouter.sol:TridentRouter",
        "label": "whitelistedPools",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_address,t_bool)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      }
    }
  }
}