{
  "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_masterAdmin",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapperAdder",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapperSetter",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_strategyAdder",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_mechanicsRegistry",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "AsyncStrategySwapperSet",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_receivedAmount",
          "type": "uint256"
        }
      ],
      "name": "AsyncTradeExecuted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        }
      ],
      "name": "AsyncTradeExpired",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "DustSent",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "previousAdminRole",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "newAdminRole",
          "type": "bytes32"
        }
      ],
      "name": "RoleAdminChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleGranted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleRevoked",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "SwapperAdded",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_token",
          "type": "address"
        }
      ],
      "name": "SwapperAndTokenEnabled",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "SwapperRemoved",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "SyncStrategySwapperSet",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_tokenIn",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_tokenOut",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_amountIn",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_maxSlippage",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "_data",
          "type": "bytes"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_receivedAmount",
          "type": "uint256"
        }
      ],
      "name": "SyncTradeExecuted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        }
      ],
      "name": "TradeCanceled",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_tokenIn",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_tokenOut",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_amountIn",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_maxSlippage",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_deadline",
          "type": "uint256"
        }
      ],
      "name": "TradeCreated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "_ids",
          "type": "uint256[]"
        }
      ],
      "name": "TradesCanceled",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "_ids",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newSwapper",
          "type": "address"
        }
      ],
      "name": "TradesSwapperChanged",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "DEFAULT_ADMIN_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "ETH_ADDRESS",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "MASTER_ADMIN",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "STRATEGY",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "STRATEGY_ADDER",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "SWAPPER_ADDER",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "SWAPPER_SETTER",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "addSwapper",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "__swappers",
          "type": "address[]"
        }
      ],
      "name": "addSwappers",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "approvedTokensBySwappers",
      "outputs": [
        {
          "internalType": "address[]",
          "name": "_tokens",
          "type": "address[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "cancelAllPending",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "_canceledTradesIds",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        }
      ],
      "name": "cancelPending",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "changeStrategyPendingTradesSwapper",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "_changedSwapperIds",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_tokenIn",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_tokenOut",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amountIn",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_maxSlippage",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_deadline",
          "type": "uint256"
        }
      ],
      "name": "create",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "_data",
          "type": "bytes"
        }
      ],
      "name": "execute",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "_receivedAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_tokenIn",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_tokenOut",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amountIn",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_maxSlippage",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "_data",
          "type": "bytes"
        }
      ],
      "name": "execute",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "_receivedAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        }
      ],
      "name": "expire",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "_freedAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        }
      ],
      "name": "getRoleAdmin",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "grantRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "hasRole",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_mechanic",
          "type": "address"
        }
      ],
      "name": "isMechanic",
      "outputs": [
        {
          "internalType": "bool",
          "name": "_isMechanic",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "isSwapper",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "mechanicsRegistry",
      "outputs": [
        {
          "internalType": "address",
          "name": "_mechanicRegistry",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "pendingTradesById",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "_id",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_tokenIn",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_tokenOut",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amountIn",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_maxSlippage",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_deadline",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        }
      ],
      "name": "pendingTradesIds",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "_pendingIds",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "pendingTradesIds",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "_pendingIds",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "removeSwapper",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "__swappers",
          "type": "address[]"
        }
      ],
      "name": "removeSwappers",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "renounceRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "revokeRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_to",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_token",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "sendDust",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_mechanicsRegistry",
          "type": "address"
        }
      ],
      "name": "setMechanicsRegistry",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "setStrategyAsyncSwapper",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        },
        {
          "internalType": "bool",
          "name": "_migrateSwaps",
          "type": "bool"
        }
      ],
      "name": "setStrategyAsyncSwapperAsAndChangePending",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "_changedSwapperIds",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_strategy",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "setStrategySyncSwapper",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "strategyAsyncSwapper",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "strategySyncSwapper",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_swapper",
          "type": "address"
        }
      ],
      "name": "swapperStrategies",
      "outputs": [
        {
          "internalType": "address[]",
          "name": "_strategies",
          "type": "address[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "swappers",
      "outputs": [
        {
          "internalType": "address[]",
          "name": "_swappersList",
          "type": "address[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
  "receipt": {
    "to": null,
    "from": "0xB82193725471dC7bfaAB1a3AB93c7b42963F3265",
    "contractAddress": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
    "transactionIndex": 3,
    "gasUsed": "3533256",
    "logsBloom": "0x00000004000000000800000000000000080000018000000000000800000000000000008000000000000000002000000000808080000040000040000000000000000000000008004000000000000801c00000002000000000000100000000000000000000020000400000000000000800000000000000100080000000000000000002000000000000800000000000000000000000008000100000000000000000200000000000080000000040000000000000000000400000041000000000004000000000000000000001800000000000000000000000000100100000000020000000000000000000000000000000004000000000040000000000000000100000",
    "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a",
    "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
    "logs": [
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3"
        ],
        "data": "0x",
        "logIndex": 12,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3",
          "0x00000000000000000000000031abe8b1a645ac2d81201869d6ec77cf192e7d7f",
          "0x000000000000000000000000b82193725471dc7bfaab1a3ab93c7b42963f3265"
        ],
        "data": "0x",
        "logIndex": 13,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x038c8d5a0695aa8e4bf7e2d14cb85443db816cf8bdf8985d9f1a65519aeb6cd9",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3"
        ],
        "data": "0x",
        "logIndex": 14,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0xe39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b911",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3"
        ],
        "data": "0x",
        "logIndex": 15,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x038c8d5a0695aa8e4bf7e2d14cb85443db816cf8bdf8985d9f1a65519aeb6cd9",
          "0x00000000000000000000000031abe8b1a645ac2d81201869d6ec77cf192e7d7f",
          "0x000000000000000000000000b82193725471dc7bfaab1a3ab93c7b42963f3265"
        ],
        "data": "0x",
        "logIndex": 16,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0xe39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b911",
          "0x00000000000000000000000031abe8b1a645ac2d81201869d6ec77cf192e7d7f",
          "0x000000000000000000000000b82193725471dc7bfaab1a3ab93c7b42963f3265"
        ],
        "data": "0x",
        "logIndex": 17,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x49e347583a7b9e7f325e8963ee1f94127eba81e401796874b5a22f7c8f9d45f7",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e5"
        ],
        "data": "0x",
        "logIndex": 18,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x0c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e5",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3"
        ],
        "data": "0x",
        "logIndex": 19,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x3853fa6a2110CEF32aA49437F22319F888784B87",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x0c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e5",
          "0x00000000000000000000000031abe8b1a645ac2d81201869d6ec77cf192e7d7f",
          "0x000000000000000000000000b82193725471dc7bfaab1a3ab93c7b42963f3265"
        ],
        "data": "0x",
        "logIndex": 20,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      },
      {
        "transactionIndex": 3,
        "blockNumber": 18091087,
        "transactionHash": "0x0f9ae45d9aa84950de94ed186171ad6233062b63da42189ff657d2107a954c51",
        "address": "0x0000000000000000000000000000000000001010",
        "topics": [
          "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
          "0x0000000000000000000000000000000000000000000000000000000000001010",
          "0x000000000000000000000000b82193725471dc7bfaab1a3ab93c7b42963f3265",
          "0x000000000000000000000000e77bbfd8ed65720f187efdd109e38d75eaca7385"
        ],
        "data": "0x00000000000000000000000000000000000000000000000001f61b1abf388000000000000000000000000000000000000000000000000000594e132bd7cb63a40000000000000000000000000000000000000000000004b51b8ae7480a14d2680000000000000000000000000000000000000000000000005757f8111892e3a40000000000000000000000000000000000000000000004b51d810262c94d5268",
        "logIndex": 21,
        "blockHash": "0x3b1b10e0468e44a93f55dab91ec13ba8f9aa2f5b008435abb7578e1392b16b1a"
      }
    ],
    "blockNumber": 18091087,
    "cumulativeGasUsed": "4225226",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x31ABE8B1A645ac2d81201869d6eC77CF192e7d7F",
    "0x31ABE8B1A645ac2d81201869d6eC77CF192e7d7F",
    "0x31ABE8B1A645ac2d81201869d6eC77CF192e7d7F",
    "0x31ABE8B1A645ac2d81201869d6eC77CF192e7d7F",
    "0x7a99923aa2efa71178bb11294349ec1f6b23a814"
  ],
  "solcInputHash": "0eb7107d651f51015c988e0c3d67565f",
  "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapperAdder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapperSetter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategyAdder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_mechanicsRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"AsyncStrategySwapperSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_receivedAmount\",\"type\":\"uint256\"}],\"name\":\"AsyncTradeExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"AsyncTradeExpired\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DustSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"SwapperAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"SwapperAndTokenEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"SwapperRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"SyncStrategySwapperSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_tokenIn\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_maxSlippage\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_receivedAmount\",\"type\":\"uint256\"}],\"name\":\"SyncTradeExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"TradeCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_tokenIn\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_maxSlippage\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"}],\"name\":\"TradeCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"_ids\",\"type\":\"uint256[]\"}],\"name\":\"TradesCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"_ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newSwapper\",\"type\":\"address\"}],\"name\":\"TradesSwapperChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MASTER_ADMIN\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STRATEGY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STRATEGY_ADDER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SWAPPER_ADDER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SWAPPER_SETTER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"addSwapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"__swappers\",\"type\":\"address[]\"}],\"name\":\"addSwappers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"approvedTokensBySwappers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelAllPending\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_canceledTradesIds\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"cancelPending\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"changeStrategyPendingTradesSwapper\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_changedSwapperIds\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSlippage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_receivedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSlippage\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_receivedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"expire\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_freedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_mechanic\",\"type\":\"address\"}],\"name\":\"isMechanic\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"_isMechanic\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"isSwapper\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mechanicsRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"_mechanicRegistry\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pendingTradesById\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSlippage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"pendingTradesIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_pendingIds\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingTradesIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_pendingIds\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"removeSwapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"__swappers\",\"type\":\"address[]\"}],\"name\":\"removeSwappers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"sendDust\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_mechanicsRegistry\",\"type\":\"address\"}],\"name\":\"setMechanicsRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"setStrategyAsyncSwapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_migrateSwaps\",\"type\":\"bool\"}],\"name\":\"setStrategyAsyncSwapperAsAndChangePending\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_changedSwapperIds\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"setStrategySyncSwapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"strategyAsyncSwapper\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"strategySyncSwapper\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_swapper\",\"type\":\"address\"}],\"name\":\"swapperStrategies\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_strategies\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"swappers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_swappersList\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TradeFactory/TradeFactory.sol\":\"TradeFactory\"},\"evmVersion\":\"istanbul\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@lbertenasco/contract-utils/contracts/utils/CollectableDust.sol\":{\"content\":\"\\n// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport '../../interfaces/utils/ICollectableDust.sol';\\n\\nabstract\\ncontract CollectableDust is ICollectableDust {\\n  using SafeERC20 for IERC20;\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  address public constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n  EnumerableSet.AddressSet internal protocolTokens;\\n\\n  constructor() {}\\n\\n  function _addProtocolToken(address _token) internal {\\n    require(!protocolTokens.contains(_token), 'collectable-dust/token-is-part-of-the-protocol');\\n    protocolTokens.add(_token);\\n  }\\n\\n  function _removeProtocolToken(address _token) internal {\\n    require(protocolTokens.contains(_token), 'collectable-dust/token-not-part-of-the-protocol');\\n    protocolTokens.remove(_token);\\n  }\\n\\n  function _sendDust(\\n    address _to,\\n    address _token,\\n    uint256 _amount\\n  ) internal {\\n    require(_to != address(0), 'collectable-dust/cant-send-dust-to-zero-address');\\n    require(!protocolTokens.contains(_token), 'collectable-dust/token-is-part-of-the-protocol');\\n    if (_token == ETH_ADDRESS) {\\n      payable(_to).transfer(_amount);\\n    } else {\\n      IERC20(_token).safeTransfer(_to, _amount);\\n    }\\n    emit DustSent(_to, _token, _amount);\\n  }\\n}\\n\",\"keccak256\":\"0xea815f8af6516d2d83d12d5a9bd70f798b38578ed94924a2eb0943a0f93e7803\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/contracts/utils/Governable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.4;\\n\\nimport '../../interfaces/utils/IGovernable.sol';\\n\\ncontract Governable is IGovernable {\\n  address public override governor;\\n  address public override pendingGovernor;\\n\\n  constructor(address _governor) {\\n    require(_governor != address(0), 'governable/governor-should-not-be-zero-address');\\n    governor = _governor;\\n  }\\n\\n  function setPendingGovernor(address _pendingGovernor) external virtual override onlyGovernor {\\n    _setPendingGovernor(_pendingGovernor);\\n  }\\n\\n  function acceptGovernor() external virtual override onlyPendingGovernor {\\n    _acceptGovernor();\\n  }\\n\\n  function _setPendingGovernor(address _pendingGovernor) internal {\\n    require(_pendingGovernor != address(0), 'governable/pending-governor-should-not-be-zero-addres');\\n    pendingGovernor = _pendingGovernor;\\n    emit PendingGovernorSet(_pendingGovernor);\\n  }\\n\\n  function _acceptGovernor() internal {\\n    governor = pendingGovernor;\\n    pendingGovernor = address(0);\\n    emit GovernorAccepted();\\n  }\\n\\n  function isGovernor(address _account) public view override returns (bool _isGovernor) {\\n    return _account == governor;\\n  }\\n\\n  modifier onlyGovernor {\\n    require(isGovernor(msg.sender), 'governable/only-governor');\\n    _;\\n  }\\n\\n  modifier onlyPendingGovernor {\\n    require(msg.sender == pendingGovernor, 'governable/only-pending-governor');\\n    _;\\n  }\\n}\\n\",\"keccak256\":\"0x793f77e9f581d63c8a6e7f64cabef9d10844fce8e7f61a39201664f194d8bdbc\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/contracts/utils/Machinery.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport '../../interfaces/utils/IMachinery.sol';\\nimport '../../interfaces/mechanics/IMechanicsRegistry.sol';\\n\\ncontract Machinery is IMachinery {\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  IMechanicsRegistry internal _mechanicsRegistry;\\n\\n  constructor(address __mechanicsRegistry) {\\n    _setMechanicsRegistry(__mechanicsRegistry);\\n  }\\n\\n  modifier onlyMechanic {\\n    require(_mechanicsRegistry.isMechanic(msg.sender), 'Machinery: not mechanic');\\n    _;\\n  }\\n\\n  function setMechanicsRegistry(address __mechanicsRegistry) external virtual override {\\n    _setMechanicsRegistry(__mechanicsRegistry);\\n  }\\n\\n  function _setMechanicsRegistry(address __mechanicsRegistry) internal {\\n    _mechanicsRegistry = IMechanicsRegistry(__mechanicsRegistry);\\n  }\\n\\n  // View helpers\\n  function mechanicsRegistry() external view override returns (address _mechanicRegistry) {\\n    return address(_mechanicsRegistry);\\n  }\\n\\n  function isMechanic(address _mechanic) public view override returns (bool _isMechanic) {\\n    return _mechanicsRegistry.isMechanic(_mechanic);\\n  }\\n\\n}\\n\",\"keccak256\":\"0xa24e42137dce45e51a72dfde5bfd4f44abb1d1b9a90cbab43b545c3233c8d86d\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/interfaces/mechanics/IMechanicsRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\ninterface IMechanicsRegistry {\\n    event MechanicAdded(address _mechanic);\\n    event MechanicRemoved(address _mechanic);\\n\\n    function addMechanic(address _mechanic) external;\\n\\n    function removeMechanic(address _mechanic) external;\\n\\n    function mechanics() external view returns (address[] memory _mechanicsList);\\n\\n    function isMechanic(address mechanic) external view returns (bool _isMechanic);\\n\\n}\\n\",\"keccak256\":\"0x6d32691d648433e6739a46f156f279c1e43b9b09432d6feb07fd1b9db04c85d1\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/interfaces/utils/ICollectableDust.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\ninterface ICollectableDust {\\n  event DustSent(address _to, address token, uint256 amount);\\n\\n  function sendDust(address _to, address _token, uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0xbc17399974d1bf723ee94625274454ed028f209e18e2978f3531d12a5a08a10f\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/interfaces/utils/IGovernable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\ninterface IGovernable {\\n  event PendingGovernorSet(address pendingGovernor);\\n  event GovernorAccepted();\\n\\n  function setPendingGovernor(address _pendingGovernor) external;\\n  function acceptGovernor() external;\\n\\n  function governor() external view returns (address _governor);\\n  function pendingGovernor() external view returns (address _pendingGovernor);\\n\\n  function isGovernor(address _account) external view returns (bool _isGovernor);\\n}\\n\",\"keccak256\":\"0xb28881a80a14bd691ef413aea97d65a2a3d4b9a690403c57223d0f56b5656e4e\",\"license\":\"MIT\"},\"@lbertenasco/contract-utils/interfaces/utils/IMachinery.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\ninterface IMachinery {\\n    // View helpers\\n    function mechanicsRegistry() external view returns (address _mechanicsRegistry);\\n    function isMechanic(address mechanic) external view returns (bool _isMechanic);\\n\\n    // Setters\\n    function setMechanicsRegistry(address _mechanicsRegistry) external;\\n\\n}\\n\",\"keccak256\":\"0xa5dd7e40d7414cd417bbd7841b9b4c1a83122bfdf7d961430b49af1b39981003\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n    function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n    function grantRole(bytes32 role, address account) external;\\n\\n    function revokeRole(bytes32 role, address account) external;\\n\\n    function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n *     require(hasRole(MY_ROLE, msg.sender));\\n *     ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n    struct RoleData {\\n        mapping(address => bool) members;\\n        bytes32 adminRole;\\n    }\\n\\n    mapping(bytes32 => RoleData) private _roles;\\n\\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n    /**\\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n     *\\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n     * {RoleAdminChanged} not being emitted signaling this.\\n     *\\n     * _Available since v3.1._\\n     */\\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n    /**\\n     * @dev Emitted when `account` is granted `role`.\\n     *\\n     * `sender` is the account that originated the contract call, an admin role\\n     * bearer except when using {_setupRole}.\\n     */\\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Emitted when `account` is revoked `role`.\\n     *\\n     * `sender` is the account that originated the contract call:\\n     *   - if using `revokeRole`, it is the admin role bearer\\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n     */\\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Modifier that checks that an account has a specific role. Reverts\\n     * with a standardized message including the required role.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n     *\\n     * _Available since v4.1._\\n     */\\n    modifier onlyRole(bytes32 role) {\\n        _checkRole(role, _msgSender());\\n        _;\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) public view override returns (bool) {\\n        return _roles[role].members[account];\\n    }\\n\\n    /**\\n     * @dev Revert with a standard message if `account` is missing `role`.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n     */\\n    function _checkRole(bytes32 role, address account) internal view {\\n        if (!hasRole(role, account)) {\\n            revert(\\n                string(\\n                    abi.encodePacked(\\n                        \\\"AccessControl: account \\\",\\n                        Strings.toHexString(uint160(account), 20),\\n                        \\\" is missing role \\\",\\n                        Strings.toHexString(uint256(role), 32)\\n                    )\\n                )\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n        return _roles[role].adminRole;\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     */\\n    function renounceRole(bytes32 role, address account) public virtual override {\\n        require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event. Note that unlike {grantRole}, this function doesn't perform any\\n     * checks on the calling account.\\n     *\\n     * [WARNING]\\n     * ====\\n     * This function should only be called from the constructor when setting\\n     * up the initial roles for the system.\\n     *\\n     * Using this function in any other way is effectively circumventing the admin\\n     * system imposed by {AccessControl}.\\n     * ====\\n     */\\n    function _setupRole(bytes32 role, address account) internal virtual {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Sets `adminRole` as ``role``'s admin role.\\n     *\\n     * Emits a {RoleAdminChanged} event.\\n     */\\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n        emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n        _roles[role].adminRole = adminRole;\\n    }\\n\\n    function _grantRole(bytes32 role, address account) private {\\n        if (!hasRole(role, account)) {\\n            _roles[role].members[account] = true;\\n            emit RoleGranted(role, account, _msgSender());\\n        }\\n    }\\n\\n    function _revokeRole(bytes32 role, address account) private {\\n        if (hasRole(role, account)) {\\n            _roles[role].members[account] = false;\\n            emit RoleRevoked(role, account, _msgSender());\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x084f583de2c714665b0304529fe8b826a2809f29d03314e4dd9eea926e4bb0f3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    using Address for address;\\n\\n    function safeTransfer(\\n        IERC20 token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(\\n        IERC20 token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        require(\\n            (value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        unchecked {\\n            uint256 oldAllowance = token.allowance(address(this), spender);\\n            require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n            uint256 newAllowance = oldAllowance - value;\\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n        }\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) {\\n            // Return data is optional\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        assembly {\\n            size := extcodesize(account)\\n        }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain `call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) private pure returns (bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x3b4820cac4f127869f6eb496c1d74fa6ac86ed24071e0f94742e6aef20e7252c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n    function _msgSender() internal view virtual returns (address) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes calldata) {\\n        return msg.data;\\n    }\\n}\\n\",\"keccak256\":\"0x95098bd1d9c8dec4d80d3dedb88a0d949fa0d740ee99f2aa466bc308216ca6d5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n     */\\n    function toString(uint256 value) internal pure returns (string memory) {\\n        // Inspired by OraclizeAPI's implementation - MIT licence\\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n        if (value == 0) {\\n            return \\\"0\\\";\\n        }\\n        uint256 temp = value;\\n        uint256 digits;\\n        while (temp != 0) {\\n            digits++;\\n            temp /= 10;\\n        }\\n        bytes memory buffer = new bytes(digits);\\n        while (value != 0) {\\n            digits -= 1;\\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n            value /= 10;\\n        }\\n        return string(buffer);\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n     */\\n    function toHexString(uint256 value) internal pure returns (string memory) {\\n        if (value == 0) {\\n            return \\\"0x00\\\";\\n        }\\n        uint256 temp = value;\\n        uint256 length = 0;\\n        while (temp != 0) {\\n            length++;\\n            temp >>= 8;\\n        }\\n        return toHexString(value, length);\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n     */\\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n        bytes memory buffer = new bytes(2 * length + 2);\\n        buffer[0] = \\\"0\\\";\\n        buffer[1] = \\\"x\\\";\\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n            value >>= 4;\\n        }\\n        require(value == 0, \\\"Strings: hex length insufficient\\\");\\n        return string(buffer);\\n    }\\n}\\n\",\"keccak256\":\"0x391d3ba97ab6856a16b225d6ee29617ad15ff00db70f3b4df1ab5ea33aa47c9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IERC165).interfaceId;\\n    }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n *     // Declare a set state variable\\n *     EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n        // Position of the value in the `values` array, plus 1 because index 0\\n        // means a value is not in the set.\\n        mapping(bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Add a value to a set. O(1).\\n     *\\n     * Returns true if the value was added to the set, that is if it was not\\n     * already present.\\n     */\\n    function _add(Set storage set, bytes32 value) private returns (bool) {\\n        if (!_contains(set, value)) {\\n            set._values.push(value);\\n            // The value is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            set._indexes[value] = set._values.length;\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the value was removed from the set, that is if it was\\n     * present.\\n     */\\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\\n        // We read and store the value's index to prevent multiple reads from the same storage slot\\n        uint256 valueIndex = set._indexes[value];\\n\\n        if (valueIndex != 0) {\\n            // Equivalent to contains(set, value)\\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = valueIndex - 1;\\n            uint256 lastIndex = set._values.length - 1;\\n\\n            if (lastIndex != toDeleteIndex) {\\n                bytes32 lastvalue = set._values[lastIndex];\\n\\n                // Move the last value to the index where the value to delete is\\n                set._values[toDeleteIndex] = lastvalue;\\n                // Update the index for the moved value\\n                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\\n            }\\n\\n            // Delete the slot where the moved value was stored\\n            set._values.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete set._indexes[value];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the value is in the set. O(1).\\n     */\\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n        return set._indexes[value] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of values on the set. O(1).\\n     */\\n    function _length(Set storage set) private view returns (uint256) {\\n        return set._values.length;\\n    }\\n\\n    /**\\n     * @dev Returns the value stored at position `index` in the set. O(1).\\n     *\\n     * Note that there are no guarantees on the ordering of values inside the\\n     * array, and it may change when more values are added or removed.\\n     *\\n     * Requirements:\\n     *\\n     * - `index` must be strictly less than {length}.\\n     */\\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n        return set._values[index];\\n    }\\n\\n    // Bytes32Set\\n\\n    struct Bytes32Set {\\n        Set _inner;\\n    }\\n\\n    /**\\n     * @dev Add a value to a set. O(1).\\n     *\\n     * Returns true if the value was added to the set, that is if it was not\\n     * already present.\\n     */\\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n        return _add(set._inner, value);\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the value was removed from the set, that is if it was\\n     * present.\\n     */\\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n        return _remove(set._inner, value);\\n    }\\n\\n    /**\\n     * @dev Returns true if the value is in the set. O(1).\\n     */\\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n        return _contains(set._inner, value);\\n    }\\n\\n    /**\\n     * @dev Returns the number of values in the set. O(1).\\n     */\\n    function length(Bytes32Set storage set) internal view returns (uint256) {\\n        return _length(set._inner);\\n    }\\n\\n    /**\\n     * @dev Returns the value stored at position `index` in the set. O(1).\\n     *\\n     * Note that there are no guarantees on the ordering of values inside the\\n     * array, and it may change when more values are added or removed.\\n     *\\n     * Requirements:\\n     *\\n     * - `index` must be strictly less than {length}.\\n     */\\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n        return _at(set._inner, index);\\n    }\\n\\n    // AddressSet\\n\\n    struct AddressSet {\\n        Set _inner;\\n    }\\n\\n    /**\\n     * @dev Add a value to a set. O(1).\\n     *\\n     * Returns true if the value was added to the set, that is if it was not\\n     * already present.\\n     */\\n    function add(AddressSet storage set, address value) internal returns (bool) {\\n        return _add(set._inner, bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the value was removed from the set, that is if it was\\n     * present.\\n     */\\n    function remove(AddressSet storage set, address value) internal returns (bool) {\\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Returns true if the value is in the set. O(1).\\n     */\\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the number of values in the set. O(1).\\n     */\\n    function length(AddressSet storage set) internal view returns (uint256) {\\n        return _length(set._inner);\\n    }\\n\\n    /**\\n     * @dev Returns the value stored at position `index` in the set. O(1).\\n     *\\n     * Note that there are no guarantees on the ordering of values inside the\\n     * array, and it may change when more values are added or removed.\\n     *\\n     * Requirements:\\n     *\\n     * - `index` must be strictly less than {length}.\\n     */\\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n        return address(uint160(uint256(_at(set._inner, index))));\\n    }\\n\\n    // UintSet\\n\\n    struct UintSet {\\n        Set _inner;\\n    }\\n\\n    /**\\n     * @dev Add a value to a set. O(1).\\n     *\\n     * Returns true if the value was added to the set, that is if it was not\\n     * already present.\\n     */\\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\\n        return _add(set._inner, bytes32(value));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the value was removed from the set, that is if it was\\n     * present.\\n     */\\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n        return _remove(set._inner, bytes32(value));\\n    }\\n\\n    /**\\n     * @dev Returns true if the value is in the set. O(1).\\n     */\\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n        return _contains(set._inner, bytes32(value));\\n    }\\n\\n    /**\\n     * @dev Returns the number of values on the set. O(1).\\n     */\\n    function length(UintSet storage set) internal view returns (uint256) {\\n        return _length(set._inner);\\n    }\\n\\n    /**\\n     * @dev Returns the value stored at position `index` in the set. O(1).\\n     *\\n     * Note that there are no guarantees on the ordering of values inside the\\n     * array, and it may change when more values are added or removed.\\n     *\\n     * Requirements:\\n     *\\n     * - `index` must be strictly less than {length}.\\n     */\\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n        return uint256(_at(set._inner, index));\\n    }\\n}\\n\",\"keccak256\":\"0x211639753e28bdca7f98618f51dca3dcd08a88b57c45050eb05fa4d0053327c3\",\"license\":\"MIT\"},\"contracts/Swapper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nimport '@lbertenasco/contract-utils/contracts/utils/Governable.sol';\\nimport '@lbertenasco/contract-utils/contracts/utils/CollectableDust.sol';\\n\\ninterface ISwapper {\\n  enum SwapperType {\\n    ASYNC,\\n    SYNC\\n  }\\n\\n  event Swapped(\\n    address _receiver,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    uint256 _receivedAmount,\\n    bytes _data\\n  );\\n\\n  // solhint-disable-next-line func-name-mixedcase\\n  function SLIPPAGE_PRECISION() external view returns (uint256);\\n\\n  // solhint-disable-next-line func-name-mixedcase\\n  function TRADE_FACTORY() external view returns (address);\\n\\n  // solhint-disable-next-line func-name-mixedcase\\n  function SWAPPER_TYPE() external view returns (SwapperType);\\n\\n  function swap(\\n    address _receiver,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes calldata _data\\n  ) external returns (uint256 _receivedAmount);\\n}\\n\\nabstract contract Swapper is ISwapper, Governable, CollectableDust {\\n  using SafeERC20 for IERC20;\\n\\n  // solhint-disable-next-line var-name-mixedcase\\n  uint256 public immutable override SLIPPAGE_PRECISION = 10000; // 1 is 0.0001%, 1_000 is 0.1%\\n\\n  // solhint-disable-next-line var-name-mixedcase\\n  address public immutable override TRADE_FACTORY;\\n\\n  constructor(address _governor, address _tradeFactory) Governable(_governor) {\\n    require(_tradeFactory != address(0), 'Swapper: zero address');\\n    TRADE_FACTORY = _tradeFactory;\\n  }\\n\\n  modifier onlyTradeFactory() {\\n    require(msg.sender == TRADE_FACTORY, 'Swapper: not trade factory');\\n    _;\\n  }\\n\\n  function _assertPreSwap(\\n    address _receiver,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage\\n  ) internal pure {\\n    require(_receiver != address(0), 'Swapper: zero address');\\n    require(_tokenIn != address(0) && _tokenOut != address(0), 'Swapper: zero address');\\n    require(_amountIn > 0, 'Swapper: zero amount');\\n    require(_maxSlippage > 0, 'Swapper: zero slippage');\\n  }\\n\\n  function _executeSwap(\\n    address _receiver,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes calldata _data\\n  ) internal virtual returns (uint256 _receivedAmount);\\n\\n  function swap(\\n    address _receiver,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes calldata _data\\n  ) external virtual override onlyTradeFactory returns (uint256 _receivedAmount) {\\n    _assertPreSwap(_receiver, _tokenIn, _tokenOut, _amountIn, _maxSlippage);\\n    IERC20(_tokenIn).safeTransferFrom(TRADE_FACTORY, address(this), _amountIn);\\n    _receivedAmount = _executeSwap(_receiver, _tokenIn, _tokenOut, _amountIn, _maxSlippage, _data);\\n    emit Swapped(_receiver, _tokenIn, _tokenOut, _amountIn, _maxSlippage, _receivedAmount, _data);\\n  }\\n\\n  function sendDust(\\n    address _to,\\n    address _token,\\n    uint256 _amount\\n  ) external virtual override onlyGovernor {\\n    _sendDust(_to, _token, _amount);\\n  }\\n}\\n\",\"keccak256\":\"0xbe926351a8c6ed2132d4cd532e48a4a22f220cd7b185d6d0a5bc4de75a880b8c\",\"license\":\"MIT\"},\"contracts/TradeFactory/TradeFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\\n\\nimport '@lbertenasco/contract-utils/contracts/utils/CollectableDust.sol';\\n\\nimport './TradeFactoryPositionsHandler.sol';\\nimport './TradeFactoryExecutor.sol';\\n\\ninterface ITradeFactory is ITradeFactoryExecutor, ITradeFactoryPositionsHandler {}\\n\\ncontract TradeFactory is TradeFactoryExecutor, CollectableDust, ITradeFactory {\\n  using SafeERC20 for IERC20;\\n  using EnumerableSet for EnumerableSet.UintSet;\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  constructor(\\n    address _masterAdmin,\\n    address _swapperAdder,\\n    address _swapperSetter,\\n    address _strategyAdder,\\n    address _mechanicsRegistry\\n  )\\n    TradeFactoryAccessManager(_masterAdmin)\\n    TradeFactoryPositionsHandler(_strategyAdder)\\n    TradeFactorySwapperHandler(_swapperAdder, _swapperSetter)\\n    TradeFactoryExecutor(_mechanicsRegistry)\\n  {}\\n\\n  // Collectable Dust\\n  function sendDust(\\n    address _to,\\n    address _token,\\n    uint256 _amount\\n  ) external virtual override onlyRole(MASTER_ADMIN) {\\n    _sendDust(_to, _token, _amount);\\n  }\\n}\\n\",\"keccak256\":\"0x7094846bba852329765538cabc3e6e539a61774b30f3b178e571b7984f884cd9\",\"license\":\"MIT\"},\"contracts/TradeFactory/TradeFactoryAccessManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/access/AccessControl.sol';\\n\\nabstract contract TradeFactoryAccessManager is AccessControl {\\n  bytes32 public constant MASTER_ADMIN = keccak256('MASTER_ADMIN');\\n\\n  constructor(address _masterAdmin) {\\n    _setRoleAdmin(MASTER_ADMIN, MASTER_ADMIN);\\n    _setupRole(MASTER_ADMIN, _masterAdmin);\\n  }\\n}\\n\",\"keccak256\":\"0x8a7e3e9bdc8bbc4b15aeb156bb63a8990ff792bc02102ba71b686db9e927d217\",\"license\":\"MIT\"},\"contracts/TradeFactory/TradeFactoryExecutor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\\n\\nimport '@lbertenasco/contract-utils/contracts/utils/Machinery.sol';\\n\\nimport './TradeFactoryPositionsHandler.sol';\\n\\ninterface ITradeFactoryExecutor {\\n  event SyncTradeExecuted(\\n    address indexed _strategy,\\n    address indexed _swapper,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes _data,\\n    uint256 _receivedAmount\\n  );\\n\\n  event AsyncTradeExecuted(uint256 indexed _id, uint256 _receivedAmount);\\n\\n  event AsyncTradeExpired(uint256 indexed _id);\\n\\n  event SwapperAndTokenEnabled(address indexed _swapper, address _token);\\n\\n  function approvedTokensBySwappers(address _swapper) external view returns (address[] memory _tokens);\\n\\n  function execute(\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes calldata _data\\n  ) external returns (uint256 _receivedAmount);\\n\\n  function execute(uint256 _id, bytes calldata _data) external returns (uint256 _receivedAmount);\\n\\n  function expire(uint256 _id) external returns (uint256 _freedAmount);\\n}\\n\\nabstract contract TradeFactoryExecutor is ITradeFactoryExecutor, TradeFactoryPositionsHandler, Machinery {\\n  using SafeERC20 for IERC20;\\n  using EnumerableSet for EnumerableSet.UintSet;\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  constructor(address _mechanicsRegistry) Machinery(_mechanicsRegistry) {}\\n\\n  mapping(address => EnumerableSet.AddressSet) internal _approvedTokensBySwappers;\\n\\n  function approvedTokensBySwappers(address _swapper) external view override returns (address[] memory _tokens) {\\n    _tokens = new address[](_approvedTokensBySwappers[_swapper].length());\\n    for (uint256 i = 0; i < _approvedTokensBySwappers[_swapper].length(); i++) {\\n      _tokens[i] = _approvedTokensBySwappers[_swapper].at(i);\\n    }\\n  }\\n\\n  // Machinery\\n  function setMechanicsRegistry(address _mechanicsRegistry) external virtual override onlyRole(MASTER_ADMIN) {\\n    _setMechanicsRegistry(_mechanicsRegistry);\\n  }\\n\\n  function execute(\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    bytes calldata _data\\n  ) external override onlyRole(STRATEGY) returns (uint256 _receivedAmount) {\\n    address _swapper = strategySyncSwapper[msg.sender];\\n    require(_swappers.contains(_swapper), 'TradeFactory: invalid swapper');\\n    require(_tokenIn != address(0) && _tokenOut != address(0), 'TradeFactory: zero address');\\n    require(_amountIn > 0, 'TradeFactory: zero amount');\\n    require(_maxSlippage > 0, 'TradeFactory: zero slippage');\\n    if (!_approvedTokensBySwappers[_swapper].contains(_tokenIn)) {\\n      _enableSwapperToken(_swapper, _tokenIn);\\n    }\\n    IERC20(_tokenIn).safeTransferFrom(msg.sender, address(this), _amountIn);\\n    _receivedAmount = ISwapper(_swapper).swap(msg.sender, _tokenIn, _tokenOut, _amountIn, _maxSlippage, _data);\\n    emit SyncTradeExecuted(msg.sender, _swapper, _tokenIn, _tokenOut, _amountIn, _maxSlippage, _data, _receivedAmount);\\n  }\\n\\n  // TradeFactoryExecutor\\n  function execute(uint256 _id, bytes calldata _data) external override onlyMechanic returns (uint256 _receivedAmount) {\\n    require(_pendingTradesIds.contains(_id), 'TradeFactory: trade not pending');\\n    Trade memory _trade = pendingTradesById[_id];\\n    require(block.timestamp <= _trade._deadline, 'TradeFactory: trade has expired');\\n    require(_swappers.contains(_trade._swapper), 'TradeFactory: invalid swapper');\\n    if (!_approvedTokensBySwappers[_trade._swapper].contains(_trade._tokenIn)) {\\n      _enableSwapperToken(_trade._swapper, _trade._tokenIn);\\n    }\\n    IERC20(_trade._tokenIn).safeTransferFrom(_trade._strategy, address(this), _trade._amountIn);\\n\\n    _receivedAmount = ISwapper(_trade._swapper).swap(\\n      _trade._strategy,\\n      _trade._tokenIn,\\n      _trade._tokenOut,\\n      _trade._amountIn,\\n      _trade._maxSlippage,\\n      _data\\n    );\\n\\n    _removePendingTrade(_trade._strategy, _id);\\n    emit AsyncTradeExecuted(_id, _receivedAmount);\\n  }\\n\\n  function expire(uint256 _id) external override onlyMechanic returns (uint256 _freedAmount) {\\n    require(_pendingTradesIds.contains(_id), 'TradeFactory: trade not pending');\\n    Trade memory _trade = pendingTradesById[_id];\\n    require(_trade._deadline <= block.timestamp, 'TradeFactory: trade not expired');\\n    _freedAmount = _trade._amountIn;\\n    // We have to take tokens from strategy, to decrease the allowance\\n    IERC20(_trade._tokenIn).safeTransferFrom(_trade._strategy, address(this), _trade._amountIn);\\n    // Send tokens back to strategy\\n    IERC20(_trade._tokenIn).safeTransfer(_trade._strategy, _trade._amountIn);\\n    // Remove trade\\n    _removePendingTrade(_trade._strategy, _id);\\n    emit AsyncTradeExpired(_id);\\n  }\\n\\n  function _enableSwapperToken(address _swapper, address _token) internal {\\n    IERC20(_token).safeApprove(_swapper, type(uint256).max);\\n    _approvedTokensBySwappers[_swapper].add(_token);\\n    emit SwapperAndTokenEnabled(_swapper, _token);\\n  }\\n}\\n\",\"keccak256\":\"0x1b8e3e370ac28b419e104d5167c906658a0eb7e18f0bab4784c8a7c849e75d80\",\"license\":\"MIT\"},\"contracts/TradeFactory/TradeFactoryPositionsHandler.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\\nimport './TradeFactorySwapperHandler.sol';\\nimport '../Swapper.sol';\\n\\ninterface ITradeFactoryPositionsHandler {\\n  struct Trade {\\n    uint256 _id;\\n    address _strategy;\\n    address _swapper;\\n    address _tokenIn;\\n    address _tokenOut;\\n    uint256 _amountIn;\\n    uint256 _maxSlippage;\\n    uint256 _deadline;\\n  }\\n\\n  event TradeCreated(\\n    uint256 indexed _id,\\n    address _strategy,\\n    address _swapper,\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    uint256 _deadline\\n  );\\n\\n  event TradeCanceled(address indexed _strategy, uint256 indexed _id);\\n\\n  event TradesCanceled(address indexed _strategy, uint256[] _ids);\\n\\n  event TradesSwapperChanged(address indexed _strategy, uint256[] _ids, address _newSwapper);\\n\\n  function pendingTradesById(uint256)\\n    external\\n    view\\n    returns (\\n      uint256 _id,\\n      address _strategy,\\n      address _swapper,\\n      address _tokenIn,\\n      address _tokenOut,\\n      uint256 _amountIn,\\n      uint256 _maxSlippage,\\n      uint256 _deadline\\n    );\\n\\n  function pendingTradesIds() external view returns (uint256[] memory _pendingIds);\\n\\n  function pendingTradesIds(address _strategy) external view returns (uint256[] memory _pendingIds);\\n\\n  function create(\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    uint256 _deadline\\n  ) external returns (uint256 _id);\\n\\n  function cancelPending(uint256 _id) external;\\n\\n  function cancelAllPending() external returns (uint256[] memory _canceledTradesIds);\\n\\n  function setStrategyAsyncSwapperAsAndChangePending(\\n    address _strategy,\\n    address _swapper,\\n    bool _migrateSwaps\\n  ) external returns (uint256[] memory _changedSwapperIds);\\n\\n  function changeStrategyPendingTradesSwapper(address _strategy, address _swapper) external returns (uint256[] memory _changedSwapperIds);\\n}\\n\\nabstract contract TradeFactoryPositionsHandler is ITradeFactoryPositionsHandler, TradeFactorySwapperHandler {\\n  using EnumerableSet for EnumerableSet.UintSet;\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  bytes32 public constant STRATEGY = keccak256('STRATEGY');\\n  bytes32 public constant STRATEGY_ADDER = keccak256('STRATEGY_ADDER');\\n\\n  uint256 private _tradeCounter = 1;\\n\\n  mapping(uint256 => Trade) public override pendingTradesById;\\n\\n  EnumerableSet.UintSet internal _pendingTradesIds;\\n\\n  mapping(address => EnumerableSet.UintSet) internal _pendingTradesByOwner;\\n\\n  constructor(address _strategyAdder) {\\n    _setRoleAdmin(STRATEGY, STRATEGY_ADDER);\\n    _setRoleAdmin(STRATEGY_ADDER, MASTER_ADMIN);\\n    _setupRole(STRATEGY_ADDER, _strategyAdder);\\n  }\\n\\n  function pendingTradesIds() external view override returns (uint256[] memory _pendingIds) {\\n    _pendingIds = new uint256[](_pendingTradesIds.length());\\n    for (uint256 i; i < _pendingTradesIds.length(); i++) {\\n      _pendingIds[i] = _pendingTradesIds.at(i);\\n    }\\n  }\\n\\n  function pendingTradesIds(address _strategy) external view override returns (uint256[] memory _pendingIds) {\\n    _pendingIds = new uint256[](_pendingTradesByOwner[_strategy].length());\\n    for (uint256 i; i < _pendingTradesByOwner[_strategy].length(); i++) {\\n      _pendingIds[i] = _pendingTradesByOwner[_strategy].at(i);\\n    }\\n  }\\n\\n  function create(\\n    address _tokenIn,\\n    address _tokenOut,\\n    uint256 _amountIn,\\n    uint256 _maxSlippage,\\n    uint256 _deadline\\n  ) external override onlyRole(STRATEGY) returns (uint256 _id) {\\n    require(strategyAsyncSwapper[msg.sender] != address(0), 'TF: no strategy swapper');\\n    require(_tokenIn != address(0) && _tokenOut != address(0), 'TradeFactory: zero address');\\n    require(_amountIn > 0, 'TradeFactory: zero amount');\\n    require(_maxSlippage > 0, 'TradeFactory: zero slippage');\\n    require(block.timestamp < _deadline, 'TradeFactory: deadline too soon');\\n    _id = _tradeCounter;\\n    Trade memory _trade = Trade(\\n      _tradeCounter,\\n      msg.sender,\\n      strategyAsyncSwapper[msg.sender],\\n      _tokenIn,\\n      _tokenOut,\\n      _amountIn,\\n      _maxSlippage,\\n      _deadline\\n    );\\n    pendingTradesById[_trade._id] = _trade;\\n    _pendingTradesByOwner[msg.sender].add(_trade._id);\\n    _pendingTradesIds.add(_trade._id);\\n    _tradeCounter += 1;\\n    emit TradeCreated(\\n      _trade._id,\\n      _trade._strategy,\\n      _trade._swapper,\\n      _trade._tokenIn,\\n      _trade._tokenOut,\\n      _trade._amountIn,\\n      _trade._maxSlippage,\\n      _trade._deadline\\n    );\\n  }\\n\\n  function cancelPending(uint256 _id) external override onlyRole(STRATEGY) {\\n    require(_pendingTradesIds.contains(_id), 'TradeFactory: trade not pending');\\n    require(pendingTradesById[_id]._strategy == msg.sender, 'TradeFactory: does not own trade');\\n    Trade memory _trade = pendingTradesById[_id];\\n    _removePendingTrade(_trade._strategy, _id);\\n    emit TradeCanceled(msg.sender, _id);\\n  }\\n\\n  function cancelAllPending() external override onlyRole(STRATEGY) returns (uint256[] memory _canceledTradesIds) {\\n    require(_pendingTradesByOwner[msg.sender].length() > 0, 'TradeFactory: no trades pending from strategy');\\n    _canceledTradesIds = new uint256[](_pendingTradesByOwner[msg.sender].length());\\n    for (uint256 i; i < _pendingTradesByOwner[msg.sender].length(); i++) {\\n      _canceledTradesIds[i] = _pendingTradesByOwner[msg.sender].at(i);\\n    }\\n    for (uint256 i; i < _canceledTradesIds.length; i++) {\\n      _removePendingTrade(msg.sender, _canceledTradesIds[i]);\\n    }\\n    emit TradesCanceled(msg.sender, _canceledTradesIds);\\n  }\\n\\n  function setStrategyAsyncSwapperAsAndChangePending(\\n    address _strategy,\\n    address _swapper,\\n    bool _migrateSwaps\\n  ) external override onlyRole(SWAPPER_SETTER) returns (uint256[] memory _changedSwapperIds) {\\n    this.setStrategyAsyncSwapper(_strategy, _swapper);\\n    if (_migrateSwaps) {\\n      return _changeStrategyPendingTradesSwapper(_strategy, _swapper);\\n    }\\n  }\\n\\n  function changeStrategyPendingTradesSwapper(address _strategy, address _swapper)\\n    external\\n    override\\n    onlyRole(SWAPPER_SETTER)\\n    returns (uint256[] memory _changedSwapperIds)\\n  {\\n    require(_swappers.contains(_swapper), 'TradeFactory: invalid swapper');\\n    return _changeStrategyPendingTradesSwapper(_strategy, _swapper);\\n  }\\n\\n  function _changeStrategyPendingTradesSwapper(address _strategy, address _swapper) internal returns (uint256[] memory _changedSwapperIds) {\\n    _changedSwapperIds = new uint256[](_pendingTradesByOwner[_strategy].length());\\n    for (uint256 i; i < _pendingTradesByOwner[_strategy].length(); i++) {\\n      pendingTradesById[_pendingTradesByOwner[_strategy].at(i)]._swapper = _swapper;\\n      _changedSwapperIds[i] = _pendingTradesByOwner[_strategy].at(i);\\n    }\\n    emit TradesSwapperChanged(_strategy, _changedSwapperIds, _swapper);\\n  }\\n\\n  function _removePendingTrade(address _strategy, uint256 _id) internal {\\n    _pendingTradesByOwner[_strategy].remove(_id);\\n    _pendingTradesIds.remove(_id);\\n    delete pendingTradesById[_id];\\n  }\\n}\\n\",\"keccak256\":\"0x97c1bbbe3340cafd8465e77aa1b1ba4ec0e7ea0787f22eafd76d1d97083c2436\",\"license\":\"MIT\"},\"contracts/TradeFactory/TradeFactorySwapperHandler.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.4;\\n\\nimport '@openzeppelin/contracts/access/AccessControl.sol';\\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\\n\\nimport '../Swapper.sol';\\nimport './TradeFactoryAccessManager.sol';\\n\\ninterface ITradeFactorySwapperHandler {\\n  event SyncStrategySwapperSet(address indexed _strategy, address _swapper);\\n  event AsyncStrategySwapperSet(address indexed _strategy, address _swapper);\\n  event SwapperAdded(address _swapper);\\n  event SwapperRemoved(address _swapper);\\n\\n  function strategySyncSwapper(address _strategy) external view returns (address _swapper);\\n\\n  function strategyAsyncSwapper(address _strategy) external view returns (address _swapper);\\n\\n  function swappers() external view returns (address[] memory _swappersList);\\n\\n  function isSwapper(address _swapper) external view returns (bool);\\n\\n  function swapperStrategies(address _swapper) external view returns (address[] memory _strategies);\\n\\n  function setStrategySyncSwapper(address _strategy, address _swapper) external;\\n\\n  function setStrategyAsyncSwapper(address _strategy, address _swapper) external;\\n\\n  function addSwapper(address _swapper) external;\\n\\n  function addSwappers(address[] memory __swappers) external;\\n\\n  function removeSwapper(address _swapper) external;\\n\\n  function removeSwappers(address[] memory __swappers) external;\\n}\\n\\nabstract contract TradeFactorySwapperHandler is ITradeFactorySwapperHandler, TradeFactoryAccessManager {\\n  using EnumerableSet for EnumerableSet.AddressSet;\\n\\n  bytes32 public constant SWAPPER_ADDER = keccak256('SWAPPER_ADDER');\\n  bytes32 public constant SWAPPER_SETTER = keccak256('SWAPPER_SETTER');\\n\\n  // swappers list\\n  EnumerableSet.AddressSet internal _swappers;\\n  // swapper -> strategy list (useful to know if we can safely deprecate a swapper)\\n  mapping(address => EnumerableSet.AddressSet) internal _swapperStrategies;\\n  // strategy -> async swapper\\n  mapping(address => address) public override strategyAsyncSwapper;\\n  // strategy -> sync swapper\\n  mapping(address => address) public override strategySyncSwapper;\\n\\n  constructor(address _swapperAdder, address _swapperSetter) {\\n    _setRoleAdmin(SWAPPER_ADDER, MASTER_ADMIN);\\n    _setRoleAdmin(SWAPPER_SETTER, MASTER_ADMIN);\\n    _setupRole(SWAPPER_ADDER, _swapperAdder);\\n    _setupRole(SWAPPER_SETTER, _swapperSetter);\\n  }\\n\\n  function isSwapper(address _swapper) external view override returns (bool) {\\n    return _swappers.contains(_swapper);\\n  }\\n\\n  function swappers() external view override returns (address[] memory _swappersList) {\\n    _swappersList = new address[](_swappers.length());\\n    for (uint256 i = 0; i < _swappers.length(); i++) {\\n      _swappersList[i] = _swappers.at(i);\\n    }\\n  }\\n\\n  function swapperStrategies(address _swapper) external view override returns (address[] memory _strategies) {\\n    _strategies = new address[](_swapperStrategies[_swapper].length());\\n    for (uint256 i = 0; i < _swapperStrategies[_swapper].length(); i++) {\\n      _strategies[i] = _swapperStrategies[_swapper].at(i);\\n    }\\n  }\\n\\n  function setStrategySyncSwapper(address _strategy, address _swapper) external override onlyRole(SWAPPER_SETTER) {\\n    // we check that swapper being added is async\\n    require(ISwapper(_swapper).SWAPPER_TYPE() == ISwapper.SwapperType.SYNC, 'TF: not sync swapper');\\n    // we check that swapper is not already added\\n    require(_swappers.contains(_swapper), 'TradeFactory: invalid swapper');\\n    // remove strategy from previous swapper if any\\n    if (strategySyncSwapper[_strategy] != address(0)) _swapperStrategies[strategySyncSwapper[_strategy]].remove(_strategy);\\n    // set new strategy's sync swapper\\n    strategySyncSwapper[_strategy] = _swapper;\\n    // add strategy into new swapper\\n    _swapperStrategies[_swapper].add(_strategy);\\n    emit SyncStrategySwapperSet(_strategy, _swapper);\\n  }\\n\\n  function setStrategyAsyncSwapper(address _strategy, address _swapper) external override onlyRole(SWAPPER_SETTER) {\\n    // we check that swapper being added is async\\n    require(ISwapper(_swapper).SWAPPER_TYPE() == ISwapper.SwapperType.ASYNC, 'TF: not async swapper');\\n    // we check that swapper is not already added\\n    require(_swappers.contains(_swapper), 'TradeFactory: invalid swapper');\\n    // remove strategy from previous swapper if any\\n    if (strategyAsyncSwapper[_strategy] != address(0)) _swapperStrategies[strategyAsyncSwapper[_strategy]].remove(_strategy);\\n    // set new strategy's async swapper\\n    strategyAsyncSwapper[_strategy] = _swapper;\\n    // add strategy into new swapper\\n    _swapperStrategies[_swapper].add(_strategy);\\n    emit AsyncStrategySwapperSet(_strategy, _swapper);\\n  }\\n\\n  function _addSwapper(address _swapper) internal {\\n    require(_swapper != address(0), 'TF: zero address');\\n    require(_swappers.add(_swapper), 'TF: swapper already added');\\n    emit SwapperAdded(_swapper);\\n  }\\n\\n  function addSwapper(address _swapper) external override onlyRole(SWAPPER_ADDER) {\\n    _addSwapper(_swapper);\\n  }\\n\\n  function addSwappers(address[] memory __swappers) external override onlyRole(SWAPPER_ADDER) {\\n    for (uint256 i = 0; i < __swappers.length; i++) {\\n      _addSwapper(__swappers[i]);\\n    }\\n  }\\n\\n  function _removeSwapper(address _swapper) internal {\\n    require(_swappers.remove(_swapper), 'TF: swapper not added');\\n    // TODO: SHOULD NOT BE ABLE TO REMOVE SWAPPER IF SWAPPER IS ASSIGNED TO STRAT\\n    emit SwapperRemoved(_swapper);\\n  }\\n\\n  function removeSwapper(address _swapper) external override onlyRole(SWAPPER_ADDER) {\\n    _removeSwapper(_swapper);\\n  }\\n\\n  function removeSwappers(address[] memory __swappers) external override onlyRole(SWAPPER_ADDER) {\\n    for (uint256 i = 0; i < __swappers.length; i++) {\\n      _removeSwapper(__swappers[i]);\\n    }\\n  }\\n}\\n\",\"keccak256\":\"0x0f1ddf83920586aefe46d0e5f420898484245155bece31a366ca014f7f0d8b7c\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405260016006553480156200001657600080fd5b5060405162003daf38038062003daf8339810160408190526200003991620002ef565b8080838686896200005a60008051602062003d8f83398151915280620001ce565b6200007560008051602062003d8f8339815191528262000222565b50620000a060008051602062003d4f83398151915260008051602062003d8f833981519152620001ce565b620000db7fe39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b91160008051602062003d8f833981519152620001ce565b620000f660008051602062003d4f8339815191528362000222565b620001227fe39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b9118262000222565b506200016090507f49e347583a7b9e7f325e8963ee1f94127eba81e401796874b5a22f7c8f9d45f760008051602062003d6f833981519152620001ce565b6200018a60008051602062003d6f83398151915260008051602062003d8f833981519152620001ce565b620001a560008051602062003d6f8339815191528262000222565b50600b80546001600160a01b0319166001600160a01b038316179055505050505050506200035e565b600082815260208190526040902060010154819060405184907fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff90600090a460009182526020829052604090912060010155565b6200022e828262000232565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200022e576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200028e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b0381168114620002ea57600080fd5b919050565b600080600080600060a0868803121562000307578081fd5b6200031286620002d2565b94506200032260208701620002d2565b93506200033260408701620002d2565b92506200034260608701620002d2565b91506200035260808701620002d2565b90509295509295909350565b6139e1806200036e6000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c8063891b1a001161013b578063c32e4f8d116100b8578063e454a5ed1161007c578063e454a5ed14610607578063ec6092ec1461062e578063ef47da6d14610641578063f48221a314610654578063f7bd381f1461066757600080fd5b8063c32e4f8d14610589578063cbf8e6c4146105b0578063cc090c32146105b8578063ccf61a41146105cb578063d547741f146105f457600080fd5b8063a217fddf116100ff578063a217fddf14610538578063a2c6f17414610540578063a734f06e14610548578063b64230ba14610563578063bf81bf431461057657600080fd5b8063891b1a00146104d95780638f05819a146104ec578063907ab008146104ff57806391d1485414610512578063993850061461052557600080fd5b80633f2d4131116101c95780635877e98e1161018d5780635877e98e146103da57806359cd24241461048b57806359efcb151461049e57806365834acc146104b1578063687020d8146104c457600080fd5b80633f2d4131146103795780634a2c1bab1461038c5780634d1dd98f1461039f57806350425491146103b45780635588fdf1146103c757600080fd5b8063248a9ca311610210578063248a9ca31461030657806329866a67146103295780632db8c1291461033e5780632f2ff15d1461035357806336568abe1461036657600080fd5b806301ffc9a71461024d57806307dc0772146102755780631078f38814610295578063185025ef146102ba578063211428c0146102dd575b600080fd5b61026061025b3660046134fb565b61067a565b60405190151581526020015b60405180910390f35b61028861028336600461324f565b6106b1565b60405161026c9190613737565b600b546001600160a01b03165b6040516001600160a01b03909116815260200161026c565b6102cf60008051602061396c83398151915281565b60405190815260200161026c565b6102a26102eb36600461324f565b6004602052600090815260409020546001600160a01b031681565b6102cf6103143660046134c1565b60009081526020819052604090206001015490565b6103316107c4565b60405161026c9190613784565b61035161034c3660046132e1565b6109d7565b005b6103516103613660046134d9565b610a13565b6103516103743660046134d9565b610a3e565b61035161038736600461324f565b610abc565b61035161039a3660046133de565b610ade565b6102cf60008051602061398c83398151915281565b6102886103c236600461324f565b610b45565b6103516103d53660046134c1565b610c52565b61043d6103e83660046134c1565b60076020819052600091825260409091208054600182015460028301546003840154600485015460058601546006870154969097015494966001600160a01b0394851696938516959285169490911692909188565b604080519889526001600160a01b0397881660208a01529587169588019590955292851660608701529316608085015260a084019290925260c083019190915260e08201526101000161026c565b61033161049936600461324f565b610db0565b6102cf6104ac36600461355a565b610eb0565b6102606104bf36600461324f565b6111ed565b6102cf60008051602061394c83398151915281565b6102cf6104e7366004613392565b61126b565b6103516104fa366004613269565b6116e9565b61035161050d3660046133de565b6118dc565b6102606105203660046134d9565b611943565b61035161053336600461324f565b61196c565b6102cf600081565b61033161198e565b6102a273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b61026061057136600461324f565b611a4c565b6102cf6105843660046134c1565b611a59565b6102cf7f0c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e581565b610288611c9b565b6103316105c636600461329b565b611d62565b6102a26105d936600461324f565b6005602052600090815260409020546001600160a01b031681565b6103516106023660046134d9565b611df9565b6102cf7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d381565b61033161063c366004613269565b611e1f565b61035161064f36600461324f565b611e73565b6102cf61066236600461331c565b611ebd565b610351610675366004613269565b612154565b60006001600160e01b03198216637965db0b60e01b14806106ab57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001600160a01b0381166000908152600c602052604090206060906106d59061233d565b67ffffffffffffffff8111156106fb57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610724578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600c6020526040902061074b9061233d565b8110156107be576001600160a01b0383166000908152600c602052604090206107749082612347565b82828151811061079457634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806107b6816138f3565b91505061072a565b50919050565b606060008051602061396c8339815191526107df813361235a565b336000908152600a602052604081206107f79061233d565b1161085f5760405162461bcd60e51b815260206004820152602d60248201527f5472616465466163746f72793a206e6f207472616465732070656e64696e672060448201526c66726f6d20737472617465677960981b60648201526084015b60405180910390fd5b336000908152600a602052604090206108779061233d565b67ffffffffffffffff81111561089d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156108c6578160200160208202803683370190505b50915060005b336000908152600a602052604090206108e49061233d565b81101561094157336000908152600a602052604090206109049082612347565b83828151811061092457634e487b7160e01b600052603260045260246000fd5b602090810291909101015280610939816138f3565b9150506108cc565b5060005b82518110156109915761097f3384838151811061097257634e487b7160e01b600052603260045260246000fd5b60200260200101516123be565b80610989816138f3565b915050610945565b50336001600160a01b03167fbc02525bfba972df6ef3d6d34e6f4773de0e098177c254a62a4926ec94fdaea6836040516109cb9190613784565b60405180910390a25090565b7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3610a02813361235a565b610a0d848484612447565b50505050565b600082815260208190526040902060010154610a2f813361235a565b610a3983836125e9565b505050565b6001600160a01b0381163314610aae5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610856565b610ab8828261266d565b5050565b60008051602061394c833981519152610ad5813361235a565b610ab8826126d2565b60008051602061394c833981519152610af7813361235a565b60005b8251811015610a3957610b33838281518110610b2657634e487b7160e01b600052603260045260246000fd5b6020026020010151612761565b80610b3d816138f3565b915050610afa565b6001600160a01b0381166000908152600360205260409020606090610b699061233d565b67ffffffffffffffff811115610b8f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610bb8578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600360205260409020610bdf9061233d565b8110156107be576001600160a01b0383166000908152600360205260409020610c089082612347565b828281518110610c2857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610c4a816138f3565b915050610bbe565b60008051602061396c833981519152610c6b813361235a565b610c7660088361283a565b610c925760405162461bcd60e51b81526004016108569061382b565b6000828152600760205260409020600101546001600160a01b03163314610cfb5760405162461bcd60e51b815260206004820181905260248201527f5472616465466163746f72793a20646f6573206e6f74206f776e2074726164656044820152606401610856565b6000828152600760208181526040928390208351610100810185528154815260018201546001600160a01b03908116938201849052600283015481169582019590955260038201548516606082015260048201549094166080850152600581015460a0850152600681015460c08501529091015460e0830152610d7e90846123be565b604051839033907fc036ffe8eab201772430a4259f57e5ed5cd8fc42ecc80be53bb03012d983aea090600090a3505050565b6001600160a01b0381166000908152600a60205260409020606090610dd49061233d565b67ffffffffffffffff811115610dfa57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e23578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600a60205260409020610e4a9061233d565b8110156107be576001600160a01b0383166000908152600a60205260409020610e739082612347565b828281518110610e9357634e487b7160e01b600052603260045260246000fd5b602090810291909101015280610ea8816138f3565b915050610e29565b600b54604051631960d2b360e21b81523360048201526000916001600160a01b0316906365834acc9060240160206040518083038186803b158015610ef457600080fd5b505afa158015610f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2c91906134a5565b610f725760405162461bcd60e51b81526020600482015260176024820152764d616368696e6572793a206e6f74206d656368616e696360481b6044820152606401610856565b610f7d60088561283a565b610f995760405162461bcd60e51b81526004016108569061382b565b6000848152600760208181526040928390208351610100810185528154815260018201546001600160a01b0390811693820193909352600282015483169481019490945260038101548216606085015260048101549091166080840152600581015460a0840152600681015460c0840152015460e082018190524211156110625760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a207472616465206861732065787069726564006044820152606401610856565b604081015161107390600190612852565b61108f5760405162461bcd60e51b8152600401610856906137f4565b60608101516040808301516001600160a01b03166000908152600c602052206110b791612852565b6110cd576110cd81604001518260600151612874565b6110f98160200151308360a0015184606001516001600160a01b03166128f1909392919063ffffffff16565b80604001516001600160a01b031663a5d4096b8260200151836060015184608001518560a001518660c001518a8a6040518863ffffffff1660e01b81526004016111499796959493929190613698565b602060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119b9190613542565b91506111ab8160200151866123be565b847ff3b176b50ba6ec4473f418ce17c562a616f7715b23a6bcea8e41d78621f56b34836040516111dd91815260200190565b60405180910390a2509392505050565b600b54604051631960d2b360e21b81526001600160a01b03838116600483015260009216906365834acc9060240160206040518083038186803b15801561123357600080fd5b505afa158015611247573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ab91906134a5565b600060008051602061396c833981519152611286813361235a565b336000908152600460205260409020546001600160a01b03166112eb5760405162461bcd60e51b815260206004820152601760248201527f54463a206e6f20737472617465677920737761707065720000000000000000006044820152606401610856565b6001600160a01b0387161580159061130b57506001600160a01b03861615155b6113575760405162461bcd60e51b815260206004820152601a60248201527f5472616465466163746f72793a207a65726f20616464726573730000000000006044820152606401610856565b600085116113a35760405162461bcd60e51b8152602060048201526019602482015278151c985919519858dd1bdc9e4e881e995c9bc8185b5bdd5b9d603a1b6044820152606401610856565b600084116113f35760405162461bcd60e51b815260206004820152601b60248201527f5472616465466163746f72793a207a65726f20736c69707061676500000000006044820152606401610856565b8242106114425760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a20646561646c696e6520746f6f20736f6f6e006044820152606401610856565b600654915060006040518061010001604052806006548152602001336001600160a01b0316815260200160046000336001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b03168152602001896001600160a01b03168152602001886001600160a01b031681526020018781526020018681526020018581525090508060076000836000015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a0820151816005015560c0820151816006015560e082015181600701559050506116158160000151600a6000336001600160a01b03166001600160a01b0316815260200190815260200160002061295c90919063ffffffff16565b5080516116249060089061295c565b506001600660008282546116389190613862565b9091555050805160208201516040808401516060850151608086015160a087015160c088015160e089015195517f399699ab6f1401e7784608cbdabe944658876a522eb163c69fd166dbf2776c4f976116d697909695949392916001600160a01b03978816815295871660208701529386166040860152919094166060840152608083019390935260a082019290925260c081019190915260e00190565b60405180910390a2505095945050505050565b60008051602061398c833981519152611702813361235a565b6000826001600160a01b031663cd985af06040518163ffffffff1660e01b815260040160206040518083038186803b15801561173d57600080fd5b505afa158015611751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117759190613523565b600181111561179457634e487b7160e01b600052602160045260246000fd5b146117d95760405162461bcd60e51b81526020600482015260156024820152742a231d103737ba1030b9bcb7319039bbb0b83832b960591b6044820152606401610856565b6117e4600183612852565b6118005760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b038381166000908152600460205260409020541615611853576001600160a01b03808416600090815260046020908152604080832054909316825260039052206118519084612968565b505b6001600160a01b03838116600090815260046020908152604080832080546001600160a01b03191694871694851790559282526003905220611895908461297d565b506040516001600160a01b0383811682528416907f1a70401259f8cfe91ae1c8d3f5b4f357d27664794f83e3bcd4648f047554f680906020015b60405180910390a2505050565b60008051602061394c8339815191526118f5813361235a565b60005b8251811015610a395761193183828151811061192457634e487b7160e01b600052603260045260246000fd5b60200260200101516126d2565b8061193b816138f3565b9150506118f8565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061394c833981519152611985813361235a565b610ab882612761565b606061199a600861233d565b67ffffffffffffffff8111156119c057634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156119e9578160200160208202803683370190505b50905060005b6119f9600861233d565b811015611a4857611a0b600882612347565b828281518110611a2b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280611a40816138f3565b9150506119ef565b5090565b60006106ab600183612852565b600b54604051631960d2b360e21b81523360048201526000916001600160a01b0316906365834acc9060240160206040518083038186803b158015611a9d57600080fd5b505afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad591906134a5565b611b1b5760405162461bcd60e51b81526020600482015260176024820152764d616368696e6572793a206e6f74206d656368616e696360481b6044820152606401610856565b611b2660088361283a565b611b425760405162461bcd60e51b81526004016108569061382b565b6000828152600760208181526040928390208351610100810185528154815260018201546001600160a01b0390811693820193909352600282015483169481019490945260038101548216606085015260048101549091166080840152600581015460a0840152600681015460c0840152015460e08201819052421015611c0b5760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a207472616465206e6f742065787069726564006044820152606401610856565b60a081015160208201516060830151919350611c32916001600160a01b03169030856128f1565b611c5c81602001518260a0015183606001516001600160a01b03166129929092919063ffffffff16565b611c6a8160200151846123be565b60405183907f9e52c476c07e14b40a7ee505cae05543e63c4c2d0c69323803c1fe0b4dd23b8a90600090a250919050565b6060611ca7600161233d565b67ffffffffffffffff811115611ccd57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611cf6578160200160208202803683370190505b50905060005b611d06600161233d565b811015611a4857611d18600182612347565b828281518110611d3857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280611d5a816138f3565b915050611cfc565b606060008051602061398c833981519152611d7d813361235a565b604051634782c0cd60e11b81526001600160a01b038087166004830152851660248201523090638f05819a90604401600060405180830381600087803b158015611dc657600080fd5b505af1158015611dda573d6000803e3d6000fd5b505050508215611df157611dee85856129c2565b91505b509392505050565b600082815260208190526040902060010154611e15813361235a565b610a39838361266d565b606060008051602061398c833981519152611e3a813361235a565b611e45600184612852565b611e615760405162461bcd60e51b8152600401610856906137f4565b611e6b84846129c2565b949350505050565b7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3611e9e813361235a565b600b80546001600160a01b0319166001600160a01b0384161790555050565b600060008051602061396c833981519152611ed8813361235a565b336000908152600560205260409020546001600160a01b0316611efc600182612852565b611f185760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b03891615801590611f3857506001600160a01b03881615155b611f845760405162461bcd60e51b815260206004820152601a60248201527f5472616465466163746f72793a207a65726f20616464726573730000000000006044820152606401610856565b60008711611fd05760405162461bcd60e51b8152602060048201526019602482015278151c985919519858dd1bdc9e4e881e995c9bc8185b5bdd5b9d603a1b6044820152606401610856565b600086116120205760405162461bcd60e51b815260206004820152601b60248201527f5472616465466163746f72793a207a65726f20736c69707061676500000000006044820152606401610856565b6001600160a01b0381166000908152600c60205260409020612042908a612852565b61205057612050818a612874565b6120656001600160a01b038a1633308a6128f1565b60405163a5d4096b60e01b81526001600160a01b0382169063a5d4096b9061209d9033908d908d908d908d908d908d90600401613698565b602060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ef9190613542565b9250806001600160a01b0316336001600160a01b03167f1d816b1b1d67ea42ff2f6dae0a85f237a27e76afccb32ba25e4175330f3703e18b8b8b8b8b8b8b60405161214097969594939291906136e8565b60405180910390a350509695505050505050565b60008051602061398c83398151915261216d813361235a565b6001826001600160a01b031663cd985af06040518163ffffffff1660e01b815260040160206040518083038186803b1580156121a857600080fd5b505afa1580156121bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e09190613523565b60018111156121ff57634e487b7160e01b600052602160045260246000fd5b146122435760405162461bcd60e51b81526020600482015260146024820152732a231d103737ba1039bcb7319039bbb0b83832b960611b6044820152606401610856565b61224e600183612852565b61226a5760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b0383811660009081526005602052604090205416156122bd576001600160a01b03808416600090815260056020908152604080832054909316825260039052206122bb9084612968565b505b6001600160a01b03838116600090815260056020908152604080832080546001600160a01b031916948716948517905592825260039052206122ff908461297d565b506040516001600160a01b0383811682528416907f09864ed308dfc2a9cc6804e3b86d38a1aaa4f7adec68be5562b9dd8feb9c1b05906020016118cf565b60006106ab825490565b60006123538383612b59565b9392505050565b6123648282611943565b610ab85761237c816001600160a01b03166014612b91565b612387836020612b91565b604051602001612398929190613623565b60408051601f198184030181529082905262461bcd60e51b8252610856916004016137c1565b6001600160a01b0382166000908152600a602052604090206123e09082612d73565b506123ec600882612d73565b50600090815260076020819052604082208281556001810180546001600160a01b0319908116909155600282018054821690556003820180548216905560048201805490911690556005810183905560068101839055015550565b6001600160a01b0383166124b55760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573742f63616e742d73656e642d647573742d60448201526e746f2d7a65726f2d6164647265737360881b6064820152608401610856565b6124c0600d83612852565b156125245760405162461bcd60e51b815260206004820152602e60248201527f636f6c6c65637461626c652d647573742f746f6b656e2d69732d706172742d6f60448201526d198b5d1a194b5c1c9bdd1bd8dbdb60921b6064820152608401610856565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612585576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561257f573d6000803e3d6000fd5b50612599565b6125996001600160a01b0383168483612992565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b6125f38282611943565b610ab8576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556126293390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6126778282611943565b15610ab8576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6126dd600182612968565b6127215760405162461bcd60e51b815260206004820152601560248201527415118e881cddd85c1c195c881b9bdd081859191959605a1b6044820152606401610856565b6040516001600160a01b03821681527f1bdacea439f3d52c1495fc881858088a33f2ad0cc4a6a1a08780ca96eb6b702d906020015b60405180910390a150565b6001600160a01b0381166127aa5760405162461bcd60e51b815260206004820152601060248201526f54463a207a65726f206164647265737360801b6044820152606401610856565b6127b560018261297d565b6128015760405162461bcd60e51b815260206004820152601960248201527f54463a207377617070657220616c7265616479206164646564000000000000006044820152606401610856565b6040516001600160a01b03821681527f459edbd4f641bfd6cb8eba5ac1b9e7a4629853efd00cc505d055fd3b051867e090602001612756565b60008181526001830160205260408120541515612353565b6001600160a01b03811660009081526001830160205260408120541515612353565b61288a6001600160a01b03821683600019612d7f565b6001600160a01b0382166000908152600c602052604090206128ac908261297d565b506040516001600160a01b0382811682528316907fca338b12f744b3a015d8436ee96c4b9c73826faed1fbb50e689f05e0ba02f5279060200160405180910390a25050565b6040516001600160a01b0380851660248301528316604482015260648101829052610a0d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612ea3565b60006123538383612f75565b6000612353836001600160a01b038416612fc4565b6000612353836001600160a01b038416612f75565b6040516001600160a01b038316602482015260448101829052610a3990849063a9059cbb60e01b90606401612925565b6001600160a01b0382166000908152600a602052604090206060906129e69061233d565b67ffffffffffffffff811115612a0c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612a35578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600a60205260409020612a5c9061233d565b811015612b0f576001600160a01b0384166000908152600a602052604081208491600791612a8a9085612347565b81526020808201929092526040908101600090812060020180546001600160a01b0319166001600160a01b039586161790559287168352600a9091529020612ad29082612347565b828281518110612af257634e487b7160e01b600052603260045260246000fd5b602090810291909101015280612b07816138f3565b915050612a3b565b50826001600160a01b03167f30b06075f2edb9220aa0b9c376183754ed018b66a4be08bf8558f33cd704255c8284604051612b4b929190613797565b60405180910390a292915050565b6000826000018281548110612b7e57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000612ba083600261387a565b612bab906002613862565b67ffffffffffffffff811115612bd157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612bfb576020820181803683370190505b509050600360fc1b81600081518110612c2457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612c6157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000612c8584600261387a565b612c90906001613862565b90505b6001811115612d24576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612cd257634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110612cf657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93612d1d816138dc565b9050612c93565b5083156123535760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610856565b60006123538383612fc4565b801580612e085750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e069190613542565b155b612e735760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610856565b6040516001600160a01b038316602482015260448101829052610a3990849063095ea7b360e01b90606401612925565b6000612ef8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130e19092919063ffffffff16565b805190915015610a395780806020019051810190612f1691906134a5565b610a395760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610856565b6000818152600183016020526040812054612fbc575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106ab565b5060006106ab565b600081815260018301602052604081205480156130d7576000612fe8600183613899565b8554909150600090612ffc90600190613899565b905081811461307d57600086600001828154811061302a57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061305b57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061309c57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106ab565b60009150506106ab565b6060611e6b848460008585843b61313a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610856565b600080866001600160a01b031685876040516131569190613607565b60006040518083038185875af1925050503d8060008114613193576040519150601f19603f3d011682016040523d82523d6000602084013e613198565b606091505b50915091506131a88282866131b3565b979650505050505050565b606083156131c2575081612353565b8251156131d25782518084602001fd5b8160405162461bcd60e51b815260040161085691906137c1565b80356001600160a01b038116811461320357600080fd5b919050565b60008083601f840112613219578182fd5b50813567ffffffffffffffff811115613230578182fd5b60208301915083602082850101111561324857600080fd5b9250929050565b600060208284031215613260578081fd5b612353826131ec565b6000806040838503121561327b578081fd5b613284836131ec565b9150613292602084016131ec565b90509250929050565b6000806000606084860312156132af578081fd5b6132b8846131ec565b92506132c6602085016131ec565b915060408401356132d68161393a565b809150509250925092565b6000806000606084860312156132f5578283fd5b6132fe846131ec565b925061330c602085016131ec565b9150604084013590509250925092565b60008060008060008060a08789031215613334578182fd5b61333d876131ec565b955061334b602088016131ec565b94506040870135935060608701359250608087013567ffffffffffffffff811115613374578283fd5b61338089828a01613208565b979a9699509497509295939492505050565b600080600080600060a086880312156133a9578081fd5b6133b2866131ec565b94506133c0602087016131ec565b94979496505050506040830135926060810135926080909101359150565b600060208083850312156133f0578182fd5b823567ffffffffffffffff80821115613407578384fd5b818501915085601f83011261341a578384fd5b81358181111561342c5761342c613924565b8060051b604051601f19603f8301168101818110858211171561345157613451613924565b604052828152858101935084860182860187018a101561346f578788fd5b8795505b8386101561349857613484816131ec565b855260019590950194938601938601613473565b5098975050505050505050565b6000602082840312156134b6578081fd5b81516123538161393a565b6000602082840312156134d2578081fd5b5035919050565b600080604083850312156134eb578182fd5b82359150613292602084016131ec565b60006020828403121561350c578081fd5b81356001600160e01b031981168114612353578182fd5b600060208284031215613534578081fd5b815160028110612353578182fd5b600060208284031215613553578081fd5b5051919050565b60008060006040848603121561356e578081fd5b83359250602084013567ffffffffffffffff81111561358b578182fd5b61359786828701613208565b9497909650939450505050565b6000815180845260208085019450808401835b838110156135d3578151875295820195908201906001016135b7565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600082516136198184602087016138b0565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161365b8160178501602088016138b0565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161368c8160288401602088016138b0565b01602801949350505050565b6001600160a01b038881168252878116602083015286166040820152606081018590526080810184905260c060a082018190526000906136db90830184866135de565b9998505050505050505050565b6001600160a01b03888116825287166020820152604081018690526060810185905260c06080820181905260009061372390830185876135de565b90508260a083015298975050505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137785783516001600160a01b031683529284019291840191600101613753565b50909695505050505050565b60208152600061235360208301846135a4565b6040815260006137aa60408301856135a4565b905060018060a01b03831660208301529392505050565b60208152600082518060208401526137e08160408501602087016138b0565b601f01601f19169190910160400192915050565b6020808252601d908201527f5472616465466163746f72793a20696e76616c69642073776170706572000000604082015260600190565b6020808252601f908201527f5472616465466163746f72793a207472616465206e6f742070656e64696e6700604082015260600190565b600082198211156138755761387561390e565b500190565b60008160001904831182151516156138945761389461390e565b500290565b6000828210156138ab576138ab61390e565b500390565b60005b838110156138cb5781810151838201526020016138b3565b83811115610a0d5750506000910152565b6000816138eb576138eb61390e565b506000190190565b60006000198214156139075761390761390e565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461394857600080fd5b5056fe038c8d5a0695aa8e4bf7e2d14cb85443db816cf8bdf8985d9f1a65519aeb6cd949e347583a7b9e7f325e8963ee1f94127eba81e401796874b5a22f7c8f9d45f7e39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b911a264697066735822122024619f67138e3289c31c8df8e130ab450d85223d6ef4e861edc8aa6290ef0ab764736f6c63430008040033038c8d5a0695aa8e4bf7e2d14cb85443db816cf8bdf8985d9f1a65519aeb6cd90c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e50b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063891b1a001161013b578063c32e4f8d116100b8578063e454a5ed1161007c578063e454a5ed14610607578063ec6092ec1461062e578063ef47da6d14610641578063f48221a314610654578063f7bd381f1461066757600080fd5b8063c32e4f8d14610589578063cbf8e6c4146105b0578063cc090c32146105b8578063ccf61a41146105cb578063d547741f146105f457600080fd5b8063a217fddf116100ff578063a217fddf14610538578063a2c6f17414610540578063a734f06e14610548578063b64230ba14610563578063bf81bf431461057657600080fd5b8063891b1a00146104d95780638f05819a146104ec578063907ab008146104ff57806391d1485414610512578063993850061461052557600080fd5b80633f2d4131116101c95780635877e98e1161018d5780635877e98e146103da57806359cd24241461048b57806359efcb151461049e57806365834acc146104b1578063687020d8146104c457600080fd5b80633f2d4131146103795780634a2c1bab1461038c5780634d1dd98f1461039f57806350425491146103b45780635588fdf1146103c757600080fd5b8063248a9ca311610210578063248a9ca31461030657806329866a67146103295780632db8c1291461033e5780632f2ff15d1461035357806336568abe1461036657600080fd5b806301ffc9a71461024d57806307dc0772146102755780631078f38814610295578063185025ef146102ba578063211428c0146102dd575b600080fd5b61026061025b3660046134fb565b61067a565b60405190151581526020015b60405180910390f35b61028861028336600461324f565b6106b1565b60405161026c9190613737565b600b546001600160a01b03165b6040516001600160a01b03909116815260200161026c565b6102cf60008051602061396c83398151915281565b60405190815260200161026c565b6102a26102eb36600461324f565b6004602052600090815260409020546001600160a01b031681565b6102cf6103143660046134c1565b60009081526020819052604090206001015490565b6103316107c4565b60405161026c9190613784565b61035161034c3660046132e1565b6109d7565b005b6103516103613660046134d9565b610a13565b6103516103743660046134d9565b610a3e565b61035161038736600461324f565b610abc565b61035161039a3660046133de565b610ade565b6102cf60008051602061398c83398151915281565b6102886103c236600461324f565b610b45565b6103516103d53660046134c1565b610c52565b61043d6103e83660046134c1565b60076020819052600091825260409091208054600182015460028301546003840154600485015460058601546006870154969097015494966001600160a01b0394851696938516959285169490911692909188565b604080519889526001600160a01b0397881660208a01529587169588019590955292851660608701529316608085015260a084019290925260c083019190915260e08201526101000161026c565b61033161049936600461324f565b610db0565b6102cf6104ac36600461355a565b610eb0565b6102606104bf36600461324f565b6111ed565b6102cf60008051602061394c83398151915281565b6102cf6104e7366004613392565b61126b565b6103516104fa366004613269565b6116e9565b61035161050d3660046133de565b6118dc565b6102606105203660046134d9565b611943565b61035161053336600461324f565b61196c565b6102cf600081565b61033161198e565b6102a273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b61026061057136600461324f565b611a4c565b6102cf6105843660046134c1565b611a59565b6102cf7f0c98cf5b298d76683bff7ac7eb2544a1c5413c08c055cad5077796993f1b71e581565b610288611c9b565b6103316105c636600461329b565b611d62565b6102a26105d936600461324f565b6005602052600090815260409020546001600160a01b031681565b6103516106023660046134d9565b611df9565b6102cf7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d381565b61033161063c366004613269565b611e1f565b61035161064f36600461324f565b611e73565b6102cf61066236600461331c565b611ebd565b610351610675366004613269565b612154565b60006001600160e01b03198216637965db0b60e01b14806106ab57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001600160a01b0381166000908152600c602052604090206060906106d59061233d565b67ffffffffffffffff8111156106fb57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610724578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600c6020526040902061074b9061233d565b8110156107be576001600160a01b0383166000908152600c602052604090206107749082612347565b82828151811061079457634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806107b6816138f3565b91505061072a565b50919050565b606060008051602061396c8339815191526107df813361235a565b336000908152600a602052604081206107f79061233d565b1161085f5760405162461bcd60e51b815260206004820152602d60248201527f5472616465466163746f72793a206e6f207472616465732070656e64696e672060448201526c66726f6d20737472617465677960981b60648201526084015b60405180910390fd5b336000908152600a602052604090206108779061233d565b67ffffffffffffffff81111561089d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156108c6578160200160208202803683370190505b50915060005b336000908152600a602052604090206108e49061233d565b81101561094157336000908152600a602052604090206109049082612347565b83828151811061092457634e487b7160e01b600052603260045260246000fd5b602090810291909101015280610939816138f3565b9150506108cc565b5060005b82518110156109915761097f3384838151811061097257634e487b7160e01b600052603260045260246000fd5b60200260200101516123be565b80610989816138f3565b915050610945565b50336001600160a01b03167fbc02525bfba972df6ef3d6d34e6f4773de0e098177c254a62a4926ec94fdaea6836040516109cb9190613784565b60405180910390a25090565b7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3610a02813361235a565b610a0d848484612447565b50505050565b600082815260208190526040902060010154610a2f813361235a565b610a3983836125e9565b505050565b6001600160a01b0381163314610aae5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610856565b610ab8828261266d565b5050565b60008051602061394c833981519152610ad5813361235a565b610ab8826126d2565b60008051602061394c833981519152610af7813361235a565b60005b8251811015610a3957610b33838281518110610b2657634e487b7160e01b600052603260045260246000fd5b6020026020010151612761565b80610b3d816138f3565b915050610afa565b6001600160a01b0381166000908152600360205260409020606090610b699061233d565b67ffffffffffffffff811115610b8f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610bb8578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600360205260409020610bdf9061233d565b8110156107be576001600160a01b0383166000908152600360205260409020610c089082612347565b828281518110610c2857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610c4a816138f3565b915050610bbe565b60008051602061396c833981519152610c6b813361235a565b610c7660088361283a565b610c925760405162461bcd60e51b81526004016108569061382b565b6000828152600760205260409020600101546001600160a01b03163314610cfb5760405162461bcd60e51b815260206004820181905260248201527f5472616465466163746f72793a20646f6573206e6f74206f776e2074726164656044820152606401610856565b6000828152600760208181526040928390208351610100810185528154815260018201546001600160a01b03908116938201849052600283015481169582019590955260038201548516606082015260048201549094166080850152600581015460a0850152600681015460c08501529091015460e0830152610d7e90846123be565b604051839033907fc036ffe8eab201772430a4259f57e5ed5cd8fc42ecc80be53bb03012d983aea090600090a3505050565b6001600160a01b0381166000908152600a60205260409020606090610dd49061233d565b67ffffffffffffffff811115610dfa57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e23578160200160208202803683370190505b50905060005b6001600160a01b0383166000908152600a60205260409020610e4a9061233d565b8110156107be576001600160a01b0383166000908152600a60205260409020610e739082612347565b828281518110610e9357634e487b7160e01b600052603260045260246000fd5b602090810291909101015280610ea8816138f3565b915050610e29565b600b54604051631960d2b360e21b81523360048201526000916001600160a01b0316906365834acc9060240160206040518083038186803b158015610ef457600080fd5b505afa158015610f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2c91906134a5565b610f725760405162461bcd60e51b81526020600482015260176024820152764d616368696e6572793a206e6f74206d656368616e696360481b6044820152606401610856565b610f7d60088561283a565b610f995760405162461bcd60e51b81526004016108569061382b565b6000848152600760208181526040928390208351610100810185528154815260018201546001600160a01b0390811693820193909352600282015483169481019490945260038101548216606085015260048101549091166080840152600581015460a0840152600681015460c0840152015460e082018190524211156110625760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a207472616465206861732065787069726564006044820152606401610856565b604081015161107390600190612852565b61108f5760405162461bcd60e51b8152600401610856906137f4565b60608101516040808301516001600160a01b03166000908152600c602052206110b791612852565b6110cd576110cd81604001518260600151612874565b6110f98160200151308360a0015184606001516001600160a01b03166128f1909392919063ffffffff16565b80604001516001600160a01b031663a5d4096b8260200151836060015184608001518560a001518660c001518a8a6040518863ffffffff1660e01b81526004016111499796959493929190613698565b602060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119b9190613542565b91506111ab8160200151866123be565b847ff3b176b50ba6ec4473f418ce17c562a616f7715b23a6bcea8e41d78621f56b34836040516111dd91815260200190565b60405180910390a2509392505050565b600b54604051631960d2b360e21b81526001600160a01b03838116600483015260009216906365834acc9060240160206040518083038186803b15801561123357600080fd5b505afa158015611247573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ab91906134a5565b600060008051602061396c833981519152611286813361235a565b336000908152600460205260409020546001600160a01b03166112eb5760405162461bcd60e51b815260206004820152601760248201527f54463a206e6f20737472617465677920737761707065720000000000000000006044820152606401610856565b6001600160a01b0387161580159061130b57506001600160a01b03861615155b6113575760405162461bcd60e51b815260206004820152601a60248201527f5472616465466163746f72793a207a65726f20616464726573730000000000006044820152606401610856565b600085116113a35760405162461bcd60e51b8152602060048201526019602482015278151c985919519858dd1bdc9e4e881e995c9bc8185b5bdd5b9d603a1b6044820152606401610856565b600084116113f35760405162461bcd60e51b815260206004820152601b60248201527f5472616465466163746f72793a207a65726f20736c69707061676500000000006044820152606401610856565b8242106114425760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a20646561646c696e6520746f6f20736f6f6e006044820152606401610856565b600654915060006040518061010001604052806006548152602001336001600160a01b0316815260200160046000336001600160a01b03166001600160a01b0316815260200190815260200160002060009054906101000a90046001600160a01b03166001600160a01b03168152602001896001600160a01b03168152602001886001600160a01b031681526020018781526020018681526020018581525090508060076000836000015181526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a0820151816005015560c0820151816006015560e082015181600701559050506116158160000151600a6000336001600160a01b03166001600160a01b0316815260200190815260200160002061295c90919063ffffffff16565b5080516116249060089061295c565b506001600660008282546116389190613862565b9091555050805160208201516040808401516060850151608086015160a087015160c088015160e089015195517f399699ab6f1401e7784608cbdabe944658876a522eb163c69fd166dbf2776c4f976116d697909695949392916001600160a01b03978816815295871660208701529386166040860152919094166060840152608083019390935260a082019290925260c081019190915260e00190565b60405180910390a2505095945050505050565b60008051602061398c833981519152611702813361235a565b6000826001600160a01b031663cd985af06040518163ffffffff1660e01b815260040160206040518083038186803b15801561173d57600080fd5b505afa158015611751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117759190613523565b600181111561179457634e487b7160e01b600052602160045260246000fd5b146117d95760405162461bcd60e51b81526020600482015260156024820152742a231d103737ba1030b9bcb7319039bbb0b83832b960591b6044820152606401610856565b6117e4600183612852565b6118005760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b038381166000908152600460205260409020541615611853576001600160a01b03808416600090815260046020908152604080832054909316825260039052206118519084612968565b505b6001600160a01b03838116600090815260046020908152604080832080546001600160a01b03191694871694851790559282526003905220611895908461297d565b506040516001600160a01b0383811682528416907f1a70401259f8cfe91ae1c8d3f5b4f357d27664794f83e3bcd4648f047554f680906020015b60405180910390a2505050565b60008051602061394c8339815191526118f5813361235a565b60005b8251811015610a395761193183828151811061192457634e487b7160e01b600052603260045260246000fd5b60200260200101516126d2565b8061193b816138f3565b9150506118f8565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061394c833981519152611985813361235a565b610ab882612761565b606061199a600861233d565b67ffffffffffffffff8111156119c057634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156119e9578160200160208202803683370190505b50905060005b6119f9600861233d565b811015611a4857611a0b600882612347565b828281518110611a2b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280611a40816138f3565b9150506119ef565b5090565b60006106ab600183612852565b600b54604051631960d2b360e21b81523360048201526000916001600160a01b0316906365834acc9060240160206040518083038186803b158015611a9d57600080fd5b505afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad591906134a5565b611b1b5760405162461bcd60e51b81526020600482015260176024820152764d616368696e6572793a206e6f74206d656368616e696360481b6044820152606401610856565b611b2660088361283a565b611b425760405162461bcd60e51b81526004016108569061382b565b6000828152600760208181526040928390208351610100810185528154815260018201546001600160a01b0390811693820193909352600282015483169481019490945260038101548216606085015260048101549091166080840152600581015460a0840152600681015460c0840152015460e08201819052421015611c0b5760405162461bcd60e51b815260206004820152601f60248201527f5472616465466163746f72793a207472616465206e6f742065787069726564006044820152606401610856565b60a081015160208201516060830151919350611c32916001600160a01b03169030856128f1565b611c5c81602001518260a0015183606001516001600160a01b03166129929092919063ffffffff16565b611c6a8160200151846123be565b60405183907f9e52c476c07e14b40a7ee505cae05543e63c4c2d0c69323803c1fe0b4dd23b8a90600090a250919050565b6060611ca7600161233d565b67ffffffffffffffff811115611ccd57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611cf6578160200160208202803683370190505b50905060005b611d06600161233d565b811015611a4857611d18600182612347565b828281518110611d3857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280611d5a816138f3565b915050611cfc565b606060008051602061398c833981519152611d7d813361235a565b604051634782c0cd60e11b81526001600160a01b038087166004830152851660248201523090638f05819a90604401600060405180830381600087803b158015611dc657600080fd5b505af1158015611dda573d6000803e3d6000fd5b505050508215611df157611dee85856129c2565b91505b509392505050565b600082815260208190526040902060010154611e15813361235a565b610a39838361266d565b606060008051602061398c833981519152611e3a813361235a565b611e45600184612852565b611e615760405162461bcd60e51b8152600401610856906137f4565b611e6b84846129c2565b949350505050565b7f0b43cb2c88b4e8fc5d4ac1352ba889b22584df0c58c4b5b589731a1c9f6f29d3611e9e813361235a565b600b80546001600160a01b0319166001600160a01b0384161790555050565b600060008051602061396c833981519152611ed8813361235a565b336000908152600560205260409020546001600160a01b0316611efc600182612852565b611f185760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b03891615801590611f3857506001600160a01b03881615155b611f845760405162461bcd60e51b815260206004820152601a60248201527f5472616465466163746f72793a207a65726f20616464726573730000000000006044820152606401610856565b60008711611fd05760405162461bcd60e51b8152602060048201526019602482015278151c985919519858dd1bdc9e4e881e995c9bc8185b5bdd5b9d603a1b6044820152606401610856565b600086116120205760405162461bcd60e51b815260206004820152601b60248201527f5472616465466163746f72793a207a65726f20736c69707061676500000000006044820152606401610856565b6001600160a01b0381166000908152600c60205260409020612042908a612852565b61205057612050818a612874565b6120656001600160a01b038a1633308a6128f1565b60405163a5d4096b60e01b81526001600160a01b0382169063a5d4096b9061209d9033908d908d908d908d908d908d90600401613698565b602060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ef9190613542565b9250806001600160a01b0316336001600160a01b03167f1d816b1b1d67ea42ff2f6dae0a85f237a27e76afccb32ba25e4175330f3703e18b8b8b8b8b8b8b60405161214097969594939291906136e8565b60405180910390a350509695505050505050565b60008051602061398c83398151915261216d813361235a565b6001826001600160a01b031663cd985af06040518163ffffffff1660e01b815260040160206040518083038186803b1580156121a857600080fd5b505afa1580156121bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e09190613523565b60018111156121ff57634e487b7160e01b600052602160045260246000fd5b146122435760405162461bcd60e51b81526020600482015260146024820152732a231d103737ba1039bcb7319039bbb0b83832b960611b6044820152606401610856565b61224e600183612852565b61226a5760405162461bcd60e51b8152600401610856906137f4565b6001600160a01b0383811660009081526005602052604090205416156122bd576001600160a01b03808416600090815260056020908152604080832054909316825260039052206122bb9084612968565b505b6001600160a01b03838116600090815260056020908152604080832080546001600160a01b031916948716948517905592825260039052206122ff908461297d565b506040516001600160a01b0383811682528416907f09864ed308dfc2a9cc6804e3b86d38a1aaa4f7adec68be5562b9dd8feb9c1b05906020016118cf565b60006106ab825490565b60006123538383612b59565b9392505050565b6123648282611943565b610ab85761237c816001600160a01b03166014612b91565b612387836020612b91565b604051602001612398929190613623565b60408051601f198184030181529082905262461bcd60e51b8252610856916004016137c1565b6001600160a01b0382166000908152600a602052604090206123e09082612d73565b506123ec600882612d73565b50600090815260076020819052604082208281556001810180546001600160a01b0319908116909155600282018054821690556003820180548216905560048201805490911690556005810183905560068101839055015550565b6001600160a01b0383166124b55760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573742f63616e742d73656e642d647573742d60448201526e746f2d7a65726f2d6164647265737360881b6064820152608401610856565b6124c0600d83612852565b156125245760405162461bcd60e51b815260206004820152602e60248201527f636f6c6c65637461626c652d647573742f746f6b656e2d69732d706172742d6f60448201526d198b5d1a194b5c1c9bdd1bd8dbdb60921b6064820152608401610856565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612585576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561257f573d6000803e3d6000fd5b50612599565b6125996001600160a01b0383168483612992565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b6125f38282611943565b610ab8576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556126293390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6126778282611943565b15610ab8576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6126dd600182612968565b6127215760405162461bcd60e51b815260206004820152601560248201527415118e881cddd85c1c195c881b9bdd081859191959605a1b6044820152606401610856565b6040516001600160a01b03821681527f1bdacea439f3d52c1495fc881858088a33f2ad0cc4a6a1a08780ca96eb6b702d906020015b60405180910390a150565b6001600160a01b0381166127aa5760405162461bcd60e51b815260206004820152601060248201526f54463a207a65726f206164647265737360801b6044820152606401610856565b6127b560018261297d565b6128015760405162461bcd60e51b815260206004820152601960248201527f54463a207377617070657220616c7265616479206164646564000000000000006044820152606401610856565b6040516001600160a01b03821681527f459edbd4f641bfd6cb8eba5ac1b9e7a4629853efd00cc505d055fd3b051867e090602001612756565b60008181526001830160205260408120541515612353565b6001600160a01b03811660009081526001830160205260408120541515612353565b61288a6001600160a01b03821683600019612d7f565b6001600160a01b0382166000908152600c602052604090206128ac908261297d565b506040516001600160a01b0382811682528316907fca338b12f744b3a015d8436ee96c4b9c73826faed1fbb50e689f05e0ba02f5279060200160405180910390a25050565b6040516001600160a01b0380851660248301528316604482015260648101829052610a0d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612ea3565b60006123538383612f75565b6000612353836001600160a01b038416612fc4565b6000612353836001600160a01b038416612f75565b6040516001600160a01b038316602482015260448101829052610a3990849063a9059cbb60e01b90606401612925565b6001600160a01b0382166000908152600a602052604090206060906129e69061233d565b67ffffffffffffffff811115612a0c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612a35578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600a60205260409020612a5c9061233d565b811015612b0f576001600160a01b0384166000908152600a602052604081208491600791612a8a9085612347565b81526020808201929092526040908101600090812060020180546001600160a01b0319166001600160a01b039586161790559287168352600a9091529020612ad29082612347565b828281518110612af257634e487b7160e01b600052603260045260246000fd5b602090810291909101015280612b07816138f3565b915050612a3b565b50826001600160a01b03167f30b06075f2edb9220aa0b9c376183754ed018b66a4be08bf8558f33cd704255c8284604051612b4b929190613797565b60405180910390a292915050565b6000826000018281548110612b7e57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000612ba083600261387a565b612bab906002613862565b67ffffffffffffffff811115612bd157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612bfb576020820181803683370190505b509050600360fc1b81600081518110612c2457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612c6157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000612c8584600261387a565b612c90906001613862565b90505b6001811115612d24576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612cd257634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110612cf657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93612d1d816138dc565b9050612c93565b5083156123535760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610856565b60006123538383612fc4565b801580612e085750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e069190613542565b155b612e735760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610856565b6040516001600160a01b038316602482015260448101829052610a3990849063095ea7b360e01b90606401612925565b6000612ef8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130e19092919063ffffffff16565b805190915015610a395780806020019051810190612f1691906134a5565b610a395760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610856565b6000818152600183016020526040812054612fbc575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106ab565b5060006106ab565b600081815260018301602052604081205480156130d7576000612fe8600183613899565b8554909150600090612ffc90600190613899565b905081811461307d57600086600001828154811061302a57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061305b57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061309c57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106ab565b60009150506106ab565b6060611e6b848460008585843b61313a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610856565b600080866001600160a01b031685876040516131569190613607565b60006040518083038185875af1925050503d8060008114613193576040519150601f19603f3d011682016040523d82523d6000602084013e613198565b606091505b50915091506131a88282866131b3565b979650505050505050565b606083156131c2575081612353565b8251156131d25782518084602001fd5b8160405162461bcd60e51b815260040161085691906137c1565b80356001600160a01b038116811461320357600080fd5b919050565b60008083601f840112613219578182fd5b50813567ffffffffffffffff811115613230578182fd5b60208301915083602082850101111561324857600080fd5b9250929050565b600060208284031215613260578081fd5b612353826131ec565b6000806040838503121561327b578081fd5b613284836131ec565b9150613292602084016131ec565b90509250929050565b6000806000606084860312156132af578081fd5b6132b8846131ec565b92506132c6602085016131ec565b915060408401356132d68161393a565b809150509250925092565b6000806000606084860312156132f5578283fd5b6132fe846131ec565b925061330c602085016131ec565b9150604084013590509250925092565b60008060008060008060a08789031215613334578182fd5b61333d876131ec565b955061334b602088016131ec565b94506040870135935060608701359250608087013567ffffffffffffffff811115613374578283fd5b61338089828a01613208565b979a9699509497509295939492505050565b600080600080600060a086880312156133a9578081fd5b6133b2866131ec565b94506133c0602087016131ec565b94979496505050506040830135926060810135926080909101359150565b600060208083850312156133f0578182fd5b823567ffffffffffffffff80821115613407578384fd5b818501915085601f83011261341a578384fd5b81358181111561342c5761342c613924565b8060051b604051601f19603f8301168101818110858211171561345157613451613924565b604052828152858101935084860182860187018a101561346f578788fd5b8795505b8386101561349857613484816131ec565b855260019590950194938601938601613473565b5098975050505050505050565b6000602082840312156134b6578081fd5b81516123538161393a565b6000602082840312156134d2578081fd5b5035919050565b600080604083850312156134eb578182fd5b82359150613292602084016131ec565b60006020828403121561350c578081fd5b81356001600160e01b031981168114612353578182fd5b600060208284031215613534578081fd5b815160028110612353578182fd5b600060208284031215613553578081fd5b5051919050565b60008060006040848603121561356e578081fd5b83359250602084013567ffffffffffffffff81111561358b578182fd5b61359786828701613208565b9497909650939450505050565b6000815180845260208085019450808401835b838110156135d3578151875295820195908201906001016135b7565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600082516136198184602087016138b0565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161365b8160178501602088016138b0565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161368c8160288401602088016138b0565b01602801949350505050565b6001600160a01b038881168252878116602083015286166040820152606081018590526080810184905260c060a082018190526000906136db90830184866135de565b9998505050505050505050565b6001600160a01b03888116825287166020820152604081018690526060810185905260c06080820181905260009061372390830185876135de565b90508260a083015298975050505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137785783516001600160a01b031683529284019291840191600101613753565b50909695505050505050565b60208152600061235360208301846135a4565b6040815260006137aa60408301856135a4565b905060018060a01b03831660208301529392505050565b60208152600082518060208401526137e08160408501602087016138b0565b601f01601f19169190910160400192915050565b6020808252601d908201527f5472616465466163746f72793a20696e76616c69642073776170706572000000604082015260600190565b6020808252601f908201527f5472616465466163746f72793a207472616465206e6f742070656e64696e6700604082015260600190565b600082198211156138755761387561390e565b500190565b60008160001904831182151516156138945761389461390e565b500290565b6000828210156138ab576138ab61390e565b500390565b60005b838110156138cb5781810151838201526020016138b3565b83811115610a0d5750506000910152565b6000816138eb576138eb61390e565b506000190190565b60006000198214156139075761390761390e565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461394857600080fd5b5056fe038c8d5a0695aa8e4bf7e2d14cb85443db816cf8bdf8985d9f1a65519aeb6cd949e347583a7b9e7f325e8963ee1f94127eba81e401796874b5a22f7c8f9d45f7e39dc63caee7a15eb0ffb77a826d10c23d40b5f7182b000737ab5c078838b911a264697066735822122024619f67138e3289c31c8df8e130ab450d85223d6ef4e861edc8aa6290ef0ab764736f6c63430008040033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "getRoleAdmin(bytes32)": {
        "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."
      },
      "grantRole(bytes32,address)": {
        "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."
      },
      "hasRole(bytes32,address)": {
        "details": "Returns `true` if `account` has been granted `role`."
      },
      "renounceRole(bytes32,address)": {
        "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`."
      },
      "revokeRole(bytes32,address)": {
        "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."
      },
      "supportsInterface(bytes4)": {
        "details": "See {IERC165-supportsInterface}."
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 516,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_roles",
        "offset": 0,
        "slot": "0",
        "type": "t_mapping(t_bytes32,t_struct(RoleData)511_storage)"
      },
      {
        "astId": 5965,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_swappers",
        "offset": 0,
        "slot": "1",
        "type": "t_struct(AddressSet)2632_storage"
      },
      {
        "astId": 5970,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_swapperStrategies",
        "offset": 0,
        "slot": "3",
        "type": "t_mapping(t_address,t_struct(AddressSet)2632_storage)"
      },
      {
        "astId": 5975,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "strategyAsyncSwapper",
        "offset": 0,
        "slot": "4",
        "type": "t_mapping(t_address,t_address)"
      },
      {
        "astId": 5980,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "strategySyncSwapper",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_address,t_address)"
      },
      {
        "astId": 5291,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_tradeCounter",
        "offset": 0,
        "slot": "6",
        "type": "t_uint256"
      },
      {
        "astId": 5297,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "pendingTradesById",
        "offset": 0,
        "slot": "7",
        "type": "t_mapping(t_uint256,t_struct(Trade)5142_storage)"
      },
      {
        "astId": 5300,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_pendingTradesIds",
        "offset": 0,
        "slot": "8",
        "type": "t_struct(UintSet)2759_storage"
      },
      {
        "astId": 5305,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_pendingTradesByOwner",
        "offset": 0,
        "slot": "10",
        "type": "t_mapping(t_address,t_struct(UintSet)2759_storage)"
      },
      {
        "astId": 272,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_mechanicsRegistry",
        "offset": 0,
        "slot": "11",
        "type": "t_contract(IMechanicsRegistry)379"
      },
      {
        "astId": 4718,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "_approvedTokensBySwappers",
        "offset": 0,
        "slot": "12",
        "type": "t_mapping(t_address,t_struct(AddressSet)2632_storage)"
      },
      {
        "astId": 21,
        "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
        "label": "protocolTokens",
        "offset": 0,
        "slot": "13",
        "type": "t_struct(AddressSet)2632_storage"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_bytes32)dyn_storage": {
        "base": "t_bytes32",
        "encoding": "dynamic_array",
        "label": "bytes32[]",
        "numberOfBytes": "32"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_contract(IMechanicsRegistry)379": {
        "encoding": "inplace",
        "label": "contract IMechanicsRegistry",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_address)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => address)",
        "numberOfBytes": "32",
        "value": "t_address"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "t_mapping(t_address,t_struct(AddressSet)2632_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct EnumerableSet.AddressSet)",
        "numberOfBytes": "32",
        "value": "t_struct(AddressSet)2632_storage"
      },
      "t_mapping(t_address,t_struct(UintSet)2759_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct EnumerableSet.UintSet)",
        "numberOfBytes": "32",
        "value": "t_struct(UintSet)2759_storage"
      },
      "t_mapping(t_bytes32,t_struct(RoleData)511_storage)": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => struct AccessControl.RoleData)",
        "numberOfBytes": "32",
        "value": "t_struct(RoleData)511_storage"
      },
      "t_mapping(t_bytes32,t_uint256)": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_uint256,t_struct(Trade)5142_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => struct ITradeFactoryPositionsHandler.Trade)",
        "numberOfBytes": "32",
        "value": "t_struct(Trade)5142_storage"
      },
      "t_struct(AddressSet)2632_storage": {
        "encoding": "inplace",
        "label": "struct EnumerableSet.AddressSet",
        "members": [
          {
            "astId": 2631,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_inner",
            "offset": 0,
            "slot": "0",
            "type": "t_struct(Set)2361_storage"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(RoleData)511_storage": {
        "encoding": "inplace",
        "label": "struct AccessControl.RoleData",
        "members": [
          {
            "astId": 508,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "members",
            "offset": 0,
            "slot": "0",
            "type": "t_mapping(t_address,t_bool)"
          },
          {
            "astId": 510,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "adminRole",
            "offset": 0,
            "slot": "1",
            "type": "t_bytes32"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(Set)2361_storage": {
        "encoding": "inplace",
        "label": "struct EnumerableSet.Set",
        "members": [
          {
            "astId": 2356,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_values",
            "offset": 0,
            "slot": "0",
            "type": "t_array(t_bytes32)dyn_storage"
          },
          {
            "astId": 2360,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_indexes",
            "offset": 0,
            "slot": "1",
            "type": "t_mapping(t_bytes32,t_uint256)"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(Trade)5142_storage": {
        "encoding": "inplace",
        "label": "struct ITradeFactoryPositionsHandler.Trade",
        "members": [
          {
            "astId": 5127,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_id",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 5129,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_strategy",
            "offset": 0,
            "slot": "1",
            "type": "t_address"
          },
          {
            "astId": 5131,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_swapper",
            "offset": 0,
            "slot": "2",
            "type": "t_address"
          },
          {
            "astId": 5133,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_tokenIn",
            "offset": 0,
            "slot": "3",
            "type": "t_address"
          },
          {
            "astId": 5135,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_tokenOut",
            "offset": 0,
            "slot": "4",
            "type": "t_address"
          },
          {
            "astId": 5137,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_amountIn",
            "offset": 0,
            "slot": "5",
            "type": "t_uint256"
          },
          {
            "astId": 5139,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_maxSlippage",
            "offset": 0,
            "slot": "6",
            "type": "t_uint256"
          },
          {
            "astId": 5141,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_deadline",
            "offset": 0,
            "slot": "7",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "256"
      },
      "t_struct(UintSet)2759_storage": {
        "encoding": "inplace",
        "label": "struct EnumerableSet.UintSet",
        "members": [
          {
            "astId": 2758,
            "contract": "contracts/TradeFactory/TradeFactory.sol:TradeFactory",
            "label": "_inner",
            "offset": 0,
            "slot": "0",
            "type": "t_struct(Set)2361_storage"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}